4
#include <stdio.h>

int main()
{
    struct bitfield 
    {
         unsigned a:5;
         unsigned c:5;
         unsigned b:6;
    } bit;

    char *ptr;
    struct bitfield bit1={1,3,3};

    ptr=&bit1;
    ptr++;

    printf("%d",*ptr);
    return 0;
}

Output to this question is 12. How is it coming? Can anyone please explain it? I tried my best to explain it.

5
  • I've never used bitfields, but since 'ptr' is of type 'char*' incrementing it would change the address it points to by 1 byte (ie. sizeof(char)) Commented Jun 16, 2013 at 5:05
  • @nishantjr- Can you explain how does that affect output ? Commented Jun 16, 2013 at 5:09
  • Give me a moment... I'm gonna write a few test programs. Which compiler do you use? Commented Jun 16, 2013 at 5:11
  • 1
    Check this stackoverflow.com/questions/10128044/… Commented Jun 16, 2013 at 5:16
  • gcc 4.3.2 ideone.com/zazd1T Commented Jun 16, 2013 at 5:17

4 Answers 4

14
+50

Explanation to this question is fairly SIMPLE :

Binary value of 1 is 00001 (as "a" have 5 bitfield)
Binary value of 3 is 00011 (as "c" have 5 bitfield)
Binary value of 3 is 000011 (as "b" have 6 bitfield)

Memory Layout can be visualized as this : enter image description here

First 5 Bits are occupied by a and have value 00001. Then 5 bits are occupied by b having value 00011 and last 6 bits by c having value 000011.

So, at starting pointer ptr is at memory location 1000, and now when you did ptr++. Since sizeof(char) is 1, ptr will move by 1 memory location. So ptr moves to memory location 1001.

Hence *ptr will give you the value stored at memory location 1001, and Hence the answer will be the 12

Sign up to request clarification or add additional context in comments.

6 Comments

@Shashank_Jain- Well this explains it more clearly ! thanks for explanation
Thanks.i thought with figure it will be easy !
The layout and organization of the bit fields is completely system dependent (assuming the system has an ABI — application binary interface — that covers the behaviour of bit fields). The size of struct bitfield is 4 on a 64-bit Intel system (Mac OS X 10.8.4). It would not be surprising to find that on a big-endian system (SPARC or PPC, for example), the result printed is zero.
@JonathanLeffler- Yes that is correct. "result is dependent on Endianness "
@Shashank_Jain - Why i can't award bounty to this answer ?
|
2

How 1 will be represented using 5 bits? It'll be 00001 and 3 will be 00011 (Note that b have 6 bitfields so it'll have additional zero: 000011).

Now lets assume that the address of bit1 is 1000. What will be ptr++? It'll be 1001 (since sizeof ptr is 1).

What does *ptr means? It means the content of the location 1001 which will be 00001100.

binary 00001100 is the decimal 12.

Comments

2

The bitfield has the following values after initialization:

000011 00011 00001
^^^^^^ ^^^^^ ^^^^^
b = 3  c = 3 a = 1

Assuming that char is 8 bits wide, you can split the 16 bits into two 8-bit parts:

00001100 01100011
^^^^^^^^ ^^^^^^^^
 ptr + 1   ptr

So you'll print the octet at ptr + 1 which is 12.

However, I'm pretty sure that this invokes undefined behavior, since the address of bitfields should not be used (let alone aliased through a pointer which is even of an incompatible type...)

4 Comments

It's not using the address of the bit field (that would be &bit1.a, etc, and would be illegal). It is using the address of a structure. The code is dubious, and implementation defined because almost everything to do with bit fields is implementation defined.
@JonathanLeffler Are you sure it's not UB? I know it is not directly using the address of the bit field, but it still disregards occasional padding, alises values through pointers of incompatible types (which breaks the strict aliasing rule which in itself undefined), etc.
It might be UB rather than IDB, but it isn't because of the 'address of bitfields' as you said (because it doesn't formally take the address of a bit field; it takes the address of a structure containing bit fields, and taking the address of the structure is fully defined). It's ugly code; all code with bit fields is moderately ugly, and then type punning and aliasing just complicate things.
@JonathanLeffler Exactly. Bit fields are evil (especially if abused...) :(
2

A program to demonstrate where a, b and c are stored. Note that it gets a bit confused because of endian-ness.

#include<stdio.h>
#include<string.h>

struct bitfield 
{
     unsigned a:5;
     unsigned c:5;
     unsigned b:6;
};

void print_bitfield(unsigned a, unsigned c, unsigned b)
{
    struct bitfield bf;
    memset(&bf, 0, sizeof(bf));
    bf.a = a;
    bf.b = b;
    bf.c = c;

    unsigned char* ptr = (unsigned char*)&bf;
    unsigned i;

    printf("%2x %2x %2x: ", a, c, b);
    for (i = 0; i < sizeof(bf); i++)
    {
        printf("%02x ", ptr[i]);
    }
    printf("\n");
}

int main()
{
    printf("sizeof bitfield: %u\n",sizeof(struct bitfield));

    printf(" a  c  b:  0  1  2  3\n");
    print_bitfield(0,  0, 0);
    print_bitfield(1,  0, 0);
    print_bitfield(31, 0, 0);
    print_bitfield(0,  1, 0);
    print_bitfield(0, 31, 0);
    print_bitfield(0,  0, 1);
    print_bitfield(0,  0, 63);
    print_bitfield(1, 3, 3);
    return 0;
}

Output:

sizeof bitfield: 4
 a  c  b:  0  1  2  3
 0  0  0: 00 00 00 00 
 1  0  0: 01 00 00 00 
1f  0  0: 1f 00 00 00 
 0  1  0: 20 00 00 00 
 0 1f  0: e0 03 00 00 
 0  0  1: 00 04 00 00 
 0  0 3f: 00 fc 00 00 
 1  3  3: 61 0c 00 00 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.