0

Code

#include <stdio.h>
struct test {
    unsigned int x; // consider int as 4 bytes
    long int y : 33; // consider long as 8 bytes
    unsigned int z;
};
int main()
{
    struct test t;
    unsigned int* ptr1 = &t.x;
    // long int* ptr3 = &t.y;
    unsigned int* ptr2 = &t.z;
    printf("sizeof(struct test)  %lu\n", sizeof(struct test));
    printf("&t.x  %u\n", ptr1);
    printf("&t.z  %u\n", ptr2);
    printf("ptr2 - ptr1  %ld\n", ptr2 - ptr1);
    return 0;
}

Output:

enter image description here

I was expecting

  • 4 bytes to be assigned for x
  • since the long int is bitfielded, 33 bits -> 4 + 4 bytes are assigned to it but only 33 is used
  • 4 bytes are then assigned to z and doesn't take up the remaining space in the previous 8 bytes because there is no 4 complete bytes left.

A total of 16 bytes and somehow it is 24

How does that work?

Also since order is important in bitfields, if x starts at 3187370912, since it is not a bitfield it gets 4 bytes. The long int gets 8 bytes, even though 33 bits are only used, since the next field is not a bitfield, so it takes additional 4 bytes. So the ptr between x and z should have 4+8 = 12 bytes difference. But the output is 4 bytes.

How does that work?

4
  • 2
    Pointer arithmetic works in units of the type, not bytes (unless the type is byte size). If your type is size 32 bits, then the 4 indicates 16 bytes. Commented Nov 29, 2022 at 19:04
  • If you change your struct to struct test {unsigned int x; unsigned int z; long int y : 33;}; it will be of size 16 because of byte padding Commented Nov 29, 2022 at 19:06
  • Pragati Bhattad, Better to use specified matching print specifiers: printf("sizeof(struct test) %zu\n", sizeof(struct test)); printf("&t.x %p\n", (void*) ptr1); printf("&t.z %p\n", (void*) ptr2); printf("ptr2 - ptr1 %td\n", ptr2 - ptr1);. Commented Nov 29, 2022 at 19:07
  • 1
    "The output is 4 bytes": no, it is 4 units. Commented Nov 29, 2022 at 19:07

1 Answer 1

0

In these calls of printf

printf("sizeof(struct test)  %lu\n", sizeof(struct test));
printf("&t.x  %u\n", ptr1);
printf("&t.z  %u\n", ptr2);
printf("ptr2 - ptr1  %ld\n", ptr2 - ptr1);

there are used wrong conversion specifiers. You need to write

printf("sizeof(struct test)  %zu\n", sizeof(struct test));
printf("&t.x  %p\n", ( void * )ptr1);
printf("&t.z  %p\n", ( void * )ptr2);
printf("ptr2 - ptr1  %td\n", ptr2 - ptr1);

As for your question then the structure is aligned by the compiler by the value of sizeof( long int ) to guarantee that the data member y will be aligned according to its type. So the compiler placed 4 padding bytes after the variable x. As a result between the pointers ptr2 and ptr1 (between the addresses of the data members z and x) of type int * there are 16 bytes. So using the pointer arithmetic the last call of printf outputted the value 4 because sizeof( int ) is equal to 4..

This bit field

long int y : 33;

is placed in one object of the type long int.

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

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.