Take the 2-minute tour ×

See the struct I used bellow. I wish to solve this problem in a portable way.

The code I used for finding the absolute address of the struct was: (char*)data - sizeof(struct block); (where data is the address to the data in the struct block). It did not work on this struct.

I made a test program seen bellow where the last assert fails.

If I change unsigned int free:1; to unsigned int free; both prints will print 12 and thus sizeof has given me the expected result.

Thanks in advance.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct block {
        size_t          size;
        struct block*   next;
        unsigned int    free:1;
        char            data[];

int main(void)
        struct block*   avail;
        struct block*   b;

        avail = malloc(sizeof(struct block) + 10);

        printf("%zu \n", sizeof(struct block)); // prints 12

        printf("%zu\n", avail->data - (char*)&avail->size); //prints 9

        b = (struct block*)((char*)avail->data - 9);
        assert(b == avail);

        b = (struct block*)((char*)avail->data - sizeof(struct block));
        assert(b == avail);

        return 0;

EDIT: seems like I found the answer here on stack overflow:

how to get struct's start address from its member's address

It gives me correct absolute address.

share|improve this question
possible duplicate of how to get struct's start address from its member's address –  RedX Jul 2 '12 at 12:49
add comment

2 Answers

The only guarantees you have regarding the layout (and size) of

struct block {
        size_t          size;
        struct block*   next;
        unsigned int    free:1;
        char            data[];

are that the addresses of the members (resp. the unit containign the bit-field) are increasing in the order of their listing, the members are suitably aligned for their types, and there's no padding at the start of the struct, so a pointer to the struct, suitably converted yields a pointer to its first member. The compiler is free to insert more padding between the members than needed for alignment.

However, usually, the padding inserted is only what is needed for alignment. Also the size and alignment requirements of size_t and struct block* are in most implementations the same, both 4 bytes on a 32 bit system and 8 bytes on a 64 bit system. Then the size of struct block is a multiple of k = sizeof(size_t), and the first k bytes are occupied by the size member, the next k bytes by the next pointer.

After that comes an unsigned bit-field of width 1. Such a small bit-field fits into any unit of storage, thus the implementation is free to choose a unit of storage of any size for it. Natural choices would be

  • one byte, since it's the smallest possible unit,
  • sizeof(int) bytes, since " A ‘‘plain’’ int object has the natural size suggested by the architecture of the execution environment".

Now, if the unit to contain the bit-field is chosen to have the size of one byte, as was the case for your implementation (and mine), the data member is typically placed directly after that, at an offset of 2*k+1 bytes, since the alignment of char is 1. If the unit for the bit-field is chosen to be int-sized, the offset of data will most likely be 2*k + sizeof(int), which on 32-bit systems is probably equal to sizeof(struct block), but not on 64-bit systems.

You can with very high probability bring the implementation to make

offsetof(struct block, data) == sizeof(struct block)

by inserting an unnamed bit-field of appropriate width (CHAR_BIT * sizeof(size_t) - 1) between free and data, but the only way that is portable and guaranteed to work is

struct block *b_addr = (struct block*)((char*)(avail->data) - offsetof(struct block, data));

as stated in Greg Hewgill's answer to the linked question.

share|improve this answer
add comment

sizeof(struct block) - sizeof(char*) should give you the size of the struct block, not including the data field. So, if you have a pointer to data, you should reach the beginning of the structure.

b = (struct block*)((char*)avail->data - (sizeof(struct block) - sizeof(char*));
assert(b == avail);

I have not tested it, though.

share|improve this answer
Flexible array members are not pointers, and do not count toward the base size of the structure, so this would yield an incorrect result. –  Justin Spahr-Summers Jul 2 '12 at 18:11
add comment

Your Answer


