To understand the bit field memory storage, I have created the test program below.
#include <stdio.h>
int main()
{
int a;
typedef struct {
int b7 : 1;
int b6 : 1;
int b5 : 1;
int b4 : 1;
int b3 : 1;
int b2 : 1;
int b1 : 1;
int b0 : 1;
} byte;
byte ab0 = {0,0,0,0,0,0,0,1};
a = *(int*)&ab0;
printf("ab0 is %x \n",a);
byte ab1 = {0,0,0,0,0,0,1,0};
a = *(int*)&ab1;
printf("ab1 is %x \n",a);
byte ab2 = {0,0,0,0,0,1,0,0};
a = *(int*)&ab2;
printf("ab2 is %x \n",a);
byte ab3 = {0,0,0,0,1,0,0,0};
a = *(int*)&ab3;
printf("ab3 is %x \n",a);
byte ab4 = {0,0,0,1,0,0,0,0};
a = *(int*)&ab4;
printf("ab4 is %x \n",a);
byte ab5 = {0,0,1,0,0,0,0,0};
a = *(int*)&ab5;
printf("ab5 is %x \n",a);
byte ab6 = {0,1,0,0,0,0,0,0};
a = *(int*)&ab6;
printf("ab6 is %x \n",a);
byte ab7 = {1,0,0,0,0,0,0,0};
a = *(int*)&ab7;
printf("ab7 is %x \n",a);
return 0;
}
Compile and run
gcc -Wall test.c
./a.out
ab0 is 80
ab1 is 40
ab2 is 20
ab3 is 10
ab4 is 8
ab5 is 4
ab6 is 2
ab7 is 1
Same output when I run code online http://codepad.org/ntqyuixp
I am not able to understand its output.
Expected Output: As per my understanding output should be like
ab0 is 1
ab1 is 2
ab2 is 4
ab3 is 8
ab4 is 10
ab5 is 20
ab6 is 40
ab7 is 80
Please let me know what I am missing.
Does endianness play any role?
How should the code be written for my expected behaviour?
The order of the bits in a bit-field is implementation defined. The implementation has a different definition from the one you expected — and that's almost all there is to say about it.
Almost everything about bit-fields is implementation defined.
¶4 The expression that specifies the width of a bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified were the colon and expression omitted.122) If the value is zero, the declaration shall have no declarator.
¶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.…
¶9 A member of a structure or union may have any complete object type other than a variably modified type.123) In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any). Such a member is called a bit-field;124) its width is preceded by a colon.
¶10 A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits.125) If the value 0 or 1 is stored into a nonzero-width bit-field of type
_Bool
, the value of the bit-field shall compare equal to the value stored; a_Bool
bit-field has the semantics of a_Bool
.¶11 An implementation may allocate any addressable storage unit large enough to hold a bitfield. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
¶12 A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field.126) As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bitfield, if any, was placed.
122) While the number of bits in a
_Bool
object is at leastCHAR_BIT
, the width (number of sign and value bits) of a_Bool
may be just 1 bit.123) A structure or union cannot contain a member with a variably modified type because member names are not ordinary identifiers as defined in 6.2.3.
124) The unary
&
(address-of) operator cannot be applied to a bit-field object; thus, there are no pointers to or arrays of bit-field objects.125) As specified in 6.7.2 above, if the actual type specifier used is
int
or a typedef-name defined asint
, then it is implementation-defined whether the bit-field is signed or unsigned.126) An unnamed bit-field structure member is useful for padding to conform to externally imposed layouts.
Note ¶11 in particular:
The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.
Note, too, that 'implementation-defined' means that the implementation must define what it does. That is, you can inspect documentation and the documentation must tell you what the compiler does (if the compiler is standard-compliant). This is different from 'unspecified' and some of the other terms you'll encounter — a compiler-writer would almost certainly not change the behaviour of bit-fields casually from release to release. In contrast, the way that arguments to functions are evaluated, for example, could change from release to release, or according to optimization options chosen at compile time, etc.
§6.5.2.2 Function calls
There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.94)
94) In other words, function executions do not ‘‘interleave’’ with each other.
6.7.2 Type specifiers
5 Each of the comma-separated multisets designates the same type, except that for bit-fields, it is implementation-defined whether the specifier
int
designates the same type assigned int
or the same type asunsigned int
.
bit fields are non portable and machine dependent.
Limitations of using bit fields
When using bit fields, be aware of the following issues:
For linux on x86 the relevant ABI document can be found here(pdf).
Specifically related to bitfields:
‘‘Plain’’ bit-fields (that is, those neither
signed
norunsigned
) always have nonnegative values. Although they may have typechar
,short
,int
, orlong
(which can have negative values), these bit-fields have the same range as a bit-field of the same size with the correspondingunsigned
type.Bit-fields obey the same size and alignment rules as other structure and union members, with the following additions:
Bit-fields are allocated from right to left (least to most significant). A bit-field must entirely reside in a storage unit appropriate for its declared type. Thus a bit-field never crosses its unit boundary.
Bit-fields may share a storage unit with other
struct
/union
members, including members that are not bit-fields. Of course,struct
members occupy different parts of the storage unit. Unnamed bit-fields’ types do not affect the alignment of a structure or union, although individual bit-fields’ member offsets obey the alignment constraints.
The
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With