Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit field's memory management in C

Tags:

c

linux

memory

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?

like image 835
Jeegar Patel Avatar asked Sep 20 '15 08:09

Jeegar Patel


3 Answers

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.

ISO/IEC 9899:2011 §6.7.2.1 Structure and union specifiers

¶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 least CHAR_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 as int, 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 as signed int or the same type as unsigned int.

like image 119
Jonathan Leffler Avatar answered Nov 20 '22 15:11

Jonathan Leffler


bit fields are non portable and machine dependent.

Limitations of using bit fields

When using bit fields, be aware of the following issues:

  1. The code will be non-portable since the organization of bits-within-bytes and bytes-within-words is machine dependent.
  2. You cannot take the address of a bit field; so the expression &mystruct.x is illegal if x is a bit field identifier, because there is no guarantee that mystruct.x lies at a byte address.
  3. Bit fields are used to pack more variables into a smaller data space, but causes the compiler to generate additional code to manipulate these variables. This costs in terms of code size and execution time.
like image 42
Nitin Tripathi Avatar answered Nov 20 '22 15:11

Nitin Tripathi


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 nor unsigned) always have nonnegative values. Although they may have type char, short, int, or long (which can have negative values), these bit-fields have the same range as a bit-field of the same size with the corresponding unsigned 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

like image 1
doron Avatar answered Nov 20 '22 14:11

doron