Reputation: 471
I have a struct in c like this
struct RegisterStruct
{
uint64_t b_0 : 64;
uint64_t b_1 : 64;
uint64_t c_0 : 64;
uint64_t c_1 : 64;
uint64_t c_2 : 64;
uint64_t d_0 : 64;
uint64_t d_1 : 64;
};
I would like to concatenate the fields into an uint64_t
integer. Each of the fields should occupy a given number of bits defined as follows:
b_0: 4bits
b_1: 4bits
c_0: 8bits
c_1: 8bits
c_2: 8bits
d_1: 16bits
d_2: 16bits
The result should be an uint64_t
integer containing the concatenated bit fields(from b_0
to d_2
) each occupying the given number of bits.
Here is what I have tried but I don't think this solution is correct:
struct RegisterStruct Register;
Register.b_0 = 8;
Register.b_1 = 8;
Register.c_0 = 128;
Register.c_1 = 128;
Register.c_2 = 128;
Register.d_0 = 32768;
Register.d_1 = 32768;
uint64_t reg_frame =Register.b_0<<60|Register.b_1<<56|Register.c_0<<48|Register.c_1<<40|Register.c_2<<32|Register.d_0<<16|Register.d_1;
Upvotes: 0
Views: 452
Reputation: 17403
You can put the structure containing the bit fields in a union with the full 64-bit unsigned integer like this:
union RegisterUnion
struct
{
uint64_t b_0 : 4;
uint64_t b_1 : 4;
uint64_t c_0 : 8;
uint64_t c_1 : 8;
uint64_t c_2 : 8;
uint64_t d_0 : 16;
uint64_t d_1 : 16;
};
uint64_t val;
};
The main problem with the above is that it is not portable. The C standard leaves the order in which bit fields are packed into their underlying storage unit type (uint64_t
in this case) as an implementation defined decision. This is entirely separate from the ordering of bytes within a multi-byte integer, i.e. the little endian versus big endian byte ordering.
In addition, using uint64_t
as the base type of a bit-field might not be supported. An implementation is only required to support bit-field members of types _Bool
, signed int
and unsigned int
(or qualified versions thereof). According to the C11 draft 6.7.2.1 paragraph 5:
- A bit-field shall have a type that is a qualified or unqualified version of
_Bool
,signed int
,unsigned int
, or some other implementation-defined type. It is implementation-defined whether atomic types are permitted.
Upvotes: 1
Reputation: 67475
typedef union
{
struct
{
uint64_t b_0 : 4;
uint64_t b_1 : 4;
uint64_t c_0 : 8;
uint64_t c_1 : 8;
uint64_t c_2 : 8;
uint64_t d_0 : 16;
uint64_t d_1 : 16;
};
uint64_t u64;
}R_t;
int main()
{
R_t Register;
Register.b_0 = 8;
Register.b_1 = 8;
Register.c_0 = 128;
Register.c_1 = 128;
Register.c_2 = 128;
Register.d_0 = 32768;
Register.d_1 = 32768;
printf("%llx\n", (long long unsigned)Register.u64);
}
Upvotes: 0