7

Here is the code in question

#include <stdio.h>

struct test {
    unsigned char t;
    unsigned short u;
    unsigned char v;
};


int main ()
{
    struct test  * a = (void *) 0x1000;

    printf("%x %p %p\n",
           sizeof(struct test),
           a + sizeof(struct test),
           a - sizeof(struct test));

    return 0;
}

The sizeof(struct test) prints 6, so I would expect to see:

6 0xffa 0x1006

Instead I get

6 0x1024 0xfdc

Last time I checked, 0x24, or 36, was not equal to 6. It's not even aligned to anything that I can tell. I am at a complete loss.

Can someone please explain to me why I'm getting these values?

endeavormac
  • 659
  • 2
  • 8
  • 18

4 Answers4

19

The problem is that when you do pointer arithmetic, it increments by a multiple of the size of the datatype.

So what you're effectively doing is adding by the square of sizeof(struct test).

Since sizeof(struct test) = 6, you are incrementing the address by 6 * 6 = 36. Hence why you get 0x1024 and 0xfdc instead of 0x1006 and 0xffa. (You also switched the + and -, but that's a small thing.)

Instead, just do this:

printf("%x %p %p\n",
       sizeof(struct test),
       a + 1,
       a - 1);
Mysticial
  • 464,885
  • 45
  • 335
  • 332
4

When you do pointer arithmetic like this, you move forward or back by that number of elements, as though that variable were in an array. So you really want to just use a + 1 and a - 1, which should advance by 6 bytes each time.

IMPORTANT: Keep in mind that the compiler can add padding in your struct to help with alignment. Don't just assume that because you have two one-byte chars and a two-byte short that your struct will be 4 bytes in size---this isn't the case here. (In fact, don't assume that you know the size of char or short; I've seen 2-byte chars before).

David Brigada
  • 594
  • 2
  • 10
  • 3
    Actually that's not quite accurate. It _can't_ add padding in between array elements. What it can do is pad in between elements of a structure and after the last element of a structure (this is probably the bit you're referring to). But the structure itself is padded to be the correct size if it has alignment requirements - the six bytes here are probably `char(1), pad(1), short(2), char(1), pad(1)` but that final padding belongs to a single structure element, it is not _between_ elements in an array made up of that structure. Nitpick mode off :-) – paxdiablo Dec 15 '11 at 04:58
  • 1
    Thanks, I've reworded my response after looking back at the C99 spec. – David Brigada Dec 15 '11 at 05:03
2

I think you are looking for a + 1 and a - 1.

(a + x) is the same is &a[x].

leppie
  • 115,091
  • 17
  • 196
  • 297
1

You have a typed pointer.

So when you increment it my 1 (i.e. a + 1) it means a + sizeof(type).

So a + sizeof(type) = a + sizeof(type) * sizeof(type) = a + 6 * 6 (in your case as sizeof(test) = 6)

That's where you are getting 0x24 or 36 from.

danishgoel
  • 3,650
  • 1
  • 18
  • 30