Angus
Angus

Reputation: 12621

Understanding the stack address manipulation

Consider the following piece of code (on a 32-bit Intel/Linux system):

struct mystruct {
  char a;
  int b;
  short c;
  char d;
};
int main()
{
  struct mystruct foo[3];
  char ch;
  int i;

  printf("%p %p %p %p %p\n", &foo[0], &foo[1], &foo[2], &ch, &i);

  return 0;
}

Which of the following would be the most likely candidate for its output?

  1. 0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8f 0xfeeece88
  2. 0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb8
  3. 0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb5
  4. 0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8c 0xfeeece88

The output is option (1). I could not understand, how the option a is the right answer..

Stack grows from higher addresses to lower addresses. Here foo[3], foo[2], foo[1], foo[0], ch, i ... i will be at the lower address of stack and foo[3] at the higher address. Here the sizeof(mystruct) is 16, hence the foo[3], foo[2], foo[1], ch will be laid with the address gap of 16.

I couldn't get the address difference 16 here with the below address:

0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8f 0xfeeece88

Upvotes: 2

Views: 86

Answers (1)

Matteo Italia
Matteo Italia

Reputation: 126787

The options that are given to you suppose a sizeof(mystruct) of 12 bytes, which is plausible, since you'll have

  • a at offset 0
  • 3 bytes of padding to keep b aligned to 4 bytes
  • b at offset 4
  • c at offset 8 (no padding required, we are already at a multiple of 2)
  • d at offset 10 (no padding required, char does not need any particular alignment)
  • 1 byte of padding to keep the next element of an array on 4 bytes boundaries (so that the b of all elements remains aligned to 4 bytes boundaries).

So, all the options are plausible in this respect; next comes ch; assuming that the compiler keeps the order of variables (which is definitely not plausible in optimized builds) will sit right over foo. foo starts at 0xfeeece90 and ch does not have alignment requirements, so it'll be 0xfeeece8f. Finally, i will sit at the nearest 4-bytes boundary above ch, which is indeed 0xfeeece88.

Again: this discussion is realistic as far as the struct is concerned, it is not when talking about the locals. In an optimized build the order of declaration does not matter, the compiler will probably reorder them to avoid wastes of space (and, if you do not ask for their address, will try to fit them in registers).

Upvotes: 4

Related Questions