Reputation: 436
I have a struct which corresponds to a register in hardware.
typedef unsigned int uint32;
typedef union A_u{
uint32 words[4];
struct {
uint32 a : 2;
uint32 b : 3;
uint32 unused : 27;
uint32 c : 2;
uint32 d : 3;
uint32 unused0 : 27;
uint32 unused1 : 1;
uint32 e : 1;
uint32 f : 1;
uint32 g : 1;
uint32 h : 1;
uint32 i : 1;
uint32 unused2 : 26;
uint32 reserved6 : 32;
}s;
}A_t;
main()
{
A_t obj;
uint32 val = 1;
memset(&obj, 0, sizeof(A_t));
//fills data
read_data(&obj);
printf("0x%x\n", obj.words[2]);
printf("obj.s.h = %d\n", obj.s.h);
}
Output is
0x80000000
obj.s.h = 1.
Though the 3rd word is 0x80000000, obj.s.h is shown as 1. I am not able to understand this. I am running this on powerpc, where First bit field is Most significant bit.
Upvotes: 4
Views: 2097
Reputation: 17613
Compilers are fairly free to do what they like so far as how memory locations line up with the members of structs and unions and other complex data structures.
I have seen mysterious run time errors using structs that were due to alignment boundary issues because one part of the source saw the struct one way and another saw it a different way.
C basically uses a struct as a template to overlay a memory area and if different files see the struct in different ways, one piece of code is calculating an address offset to a struct member that is different from another.
Some compilers will provide a pragma that will allow you to specify a pack action so that you can specify the alignment boundary of struct members.
In order to maintain compatibility with hardware, the best course seems to be to use arrays of unsigned character because that way you can index to the unsigned character array element and then select one of the eight bits with bitwise operators. You can then wrap the unsigned character array within various access functions, classes, macros, etc to manipulate the actual data that you want to read and write. Using unsigned character arrays tends to be more portable as well.
Bit fields seem to be more of a way for an application to maintain indicators and flags in a more memory conserving fashion but are not as useful for communication with entities (hardware or software) outside of the application. And depending on the compiler and the hardware on which the application is running, using bit fields may introduce a small run time penalty as bit fields are accessed and packed and unpacked.
Upvotes: 4