Is this code declaring a type? - c

#ifdef _CPU_8BIT_INT_
// unsigned 8 bit
typedef unsigned _CPU_8BIT_INT_ u8 ;
What is the code above doing? Is it trying to declare a type? (type as in integer, char etc.)

Yes, typedef is used to declare a type. From now on
u8 x;
/* Equivalent to. */
unsigned _CPU_8BIT_INT_ x;
Are you sure you're not better off using uint8_t from stdint.h ?

Related

Type conversion between Glib types (e.g. guint) to standard C data types (e.g. int)

I am working with a C code base that uses an API function (https://developer.gnome.org/glib/stable/glib-Hash-Tables.html#g-hash-table-size) that returns a guint. I needed to pass this along downstream as an int. I am wondering if there's any way to do this?
I searched the docs and Google but came up empty.
The mere existence of these typedefs baffles me. Check glib/gtypes.h:
typedef char gchar;
typedef short gshort;
typedef long glong;
typedef int gint;
typedef gint gboolean;
typedef unsigned char guchar;
typedef unsigned short gushort;
typedef unsigned long gulong;
typedef unsigned int guint;
So no conversion is needed between unsigned int and guint, they are the same type.
The usual warnings about converting between unsigned int and int apply.

I need to write a C program that uses a Union structure to set the bits of an int

Here are the instructions:
Define a union data struct WORD_T for a uint16_t integer so that a value can be assigned to a WORD_T integer in three ways:
(1) To assign the value to each bit of the integer,
(2) To assign the value to each byte of the integer,
(3) To assign the value to the integer directly.
I know I need to do something different with that first struct, but I'm pretty lost in general. Here is what I have:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#define BIT(n) (1 << n)
#define BIT_SET(var, mask) (n |= (mask) )
#define BIT_CLEAR(var, mask) (n &= ~(mask) )
#define BIT_FLIP(var, mask) (n ^= (mask) )
union WORD_T{
struct{
uint16_t integerVar:16
};
struct{
unsigned bit1:0;
unsigned bit2:0;
unsigned bit3:0;
unsigned bit4:0;
unsigned bit5:0;
unsigned bit6:0;
unsigned bit7:0;
unsigned bit8:0;
unsigned bit9:0;
unsigned bit10:0;
unsigned bit11:0;
unsigned bit12:0;
unsigned bit13:0;
unsigned bit14:0;
unsigned bit15:0;
unsigned bit16:0;
};
void setIndividualBit(unsigned value, int bit) {
mask = BIT(value) | BIT(bit);
BIT_SET(n, mask);
}
};
The most obvious problem is that :0 means "a bit-field of zero bits" which doesn't make any sense. You should change this to 1 and then you can assign individual bits through code like the_union.the_struct.bit1 = 1;.
This format is an alternative to the bit set/clear macros you wrote.
Your union should look like:
typedef union
{
uint16_t word;
uint8_t byte[2];
struct{
uint16_t bit1:1;
...
However. This is a really bad idea and your teacher should know better than to give such assignments. Bit-fields in C are a bag of worms - they are very poorly specified by the standard. Problems:
You can't know which bit that is the MSB, it is not defined.
You can't know if there will be padding bits/bytes somewhere.
You can't even use uint16_t or uint8_t because bit-fields are only specified to work with int.
And so on. In addition you have to deal with endianness and alignment. See Why bit endianness is an issue in bitfields?.
Essentially, code using bit-fields like this will rely heavily on the specific compiler. It will be completely non-portable.
All of these problems could be avoided by dropping the bit-field and use bitwise operators on a uint16_t instead, like you did in your macros. With bitwise operators only, your code will turn deterministic and 100% portable. You can even use them to dodge endianess, by using bit shifts.
Here's the union definition:
union WORD_T
{
uint16_t word;
struct
{
uint8_t byte0;
uint8_t byte1;
};
struct
{
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
uint8_t bit8:1;
uint8_t bit9:1;
uint8_t bit10:1;
uint8_t bit11:1;
uint8_t bit12:1;
uint8_t bit13:1;
uint8_t bit14:1;
uint8_t bit15:1;
};
};
To assign to the individual components, do something similar to the following:
union WORD_T data;
data.word = 0xF0F0; // (3) Assign to entire word
data.byte0 = 0xAA; // (2) Assign to individual byte
data.bit0 = 0; // (1) Assign to individual bits
data.bit1 = 1;
data.bit2 = 1;
data.bit2 = 0;

Confused about definition for pte_t and __pte(x)

typedef struct { unsigned long pte; } pte_t;
#define __pte(x) ((pte_t) { (x) } )
Why not use 'typedef unsigned long pte_t' directly?
Why '{ }' is used here? It looks weird.
I know without those the gcc will report an error. However, how it works?
I don't know the library, but I would bet that the intention is to prevent the automatic conversion between pte_t and integral types.
I mean, a typedef is just an alias for a type, so:
typedef unsigned long pte_t;
pte_t x = 3; //ok
char y = x; //ok
But a struct is a new type, so:
typedef struct { unsigned long pte; } pte_t;
pte_t x = 3; //error!
char y = x; //error!
Then provide a few functions, macros or whatever to get/set the pte_t internal field, and done.
UPDATE: Ok, I've found it. The library is the Linux kernel, and just next to it there is:
#define pte_val(x) ((x).pte)
to access the value.
But looking a bit over it, under conditionally compiled code, there is this alternative definition:
typedef struct { unsigned long pte_low, pte_high; } pte_t;
#define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
See? Depending on the configuration, there may be just one field or several of them. It would be crazy to change from a single type to a struct. So it is defined always as a struct.

how to make sizeof enum as char size in C in visual c++ IDE

I'm writing C program in VC++ 2008 I have below structure and enum.
test.h
#ifndef _TEST_H_
#define _TEST_H_
typedef enum Selection
{
None,
Single,
Multiple
} Selection_T;
typedef struct Test_struct
{
char var1;
char var2;
Selection_T sel;
} Test_struct_T;
#endif
test.c
#include "stdio.h"
#include "test.h"
Test_struct_T test_obj = { 1, 2, Multiple };
int main()
{
char *pbyte = (char *)&test_obj;
int i=0;
for(i=0;i<sizeof(test_obj);i++)
printf ("%x\n",*(pbyte+i));
getchar();
return 0;
}
I want sel should start from 3rd byte in structure but the compiler treating enum as integer so sel starts from 5th byte after (2 holes) please help me to make compiler treating enum as byte so sel should start from 3rd byte of the structure.
If there are Pragmas it'll be useful for me.
Thanks Advance
In C++11 you can declare a scoped enum with an underlying type other than the default of int. For instance:
typedef enum Selection: unsigned char
{
None,
Single,
Multiple
} Selection_T;
In C++, prior to the C++11 standard, or C this is not possible. The implementation determines the representation of an enum. In the case of the Microsoft compiler, an enum is represented as an int.
If you wish to use a single byte to store this information, it follows that you cannot use an enum and instead you should use unsigned char.
It is true that you could pack your struct, but this has disadvantages. You will now have misaligned data, and your variable is still 4 bytes wide.
In some circumstances, this may be helpful:
typedef uint8_t Selection_t;
enum Selection_enum
{
None,
Single,
Multiple
};
/* Selection_t is of size 8 */
typedef struct Test_struct
{
char var1;
char var2;
Selection_T sel;
} Test_struct_T;
On one hand type Selection_t has size 8 and can be used for variable and function parameter type.
On the other hand you can use the enum values for assignation that are of type int by default but the compiler will cast them immediately when assigned to a Selection_t type variable.
Also, if you do something unsafe like defining and using a sel = 0xFFFF, the compiler will warn you with following message:
warning: large integer implicitly truncated to unsigned type [-Woverflow]
In MSVC the following is a workable construct that I use:
typedef enum {
zero,
one
} Int;
struct test {
Int first:8;
int fill:24;
};
void main(int argc, char **argv) {
struct test mine[1];
mine->first = zero;
}

How do I solve given typedef in C

I have a couple of typedef statement but now sure whats the original type it has
typedef unsigned int addrt;
typedef addrt addr32t;
Is "addr32t" nothing but an unsigned integer??
addrt is an alias of unsigned int.
addr32t is an alias of addrt, therefore an alias of unsigned int.
Is "addr32t" nothing but an unsigned integer??
Yes.

Resources