Search code examples
cpointersstruct

Manually stepping through a struct in C


I don't understand why I can't print out ints b and c in this way:

#include "stdio.h"

typedef struct{
  int a;
  int b;
  int c;
} myStruct;

int main(){

  myStruct MS;
  MS.a = 13;
  MS.b = 27;
  MS.c = 39;

  myStruct* pMS = &MS;

  printf("pMS = %u\n", pMS );
  printf("&a = %u\n", &pMS->a );  // addr of a is addr of struct
  printf("&b = %u\n", &pMS->b );  // addr of b is +4 from a
  printf("&c = %u\n", &pMS->c );  // addr of c is +8 from a

  printf("*pMS = %d\n",*(pMS) );
  printf("*pMS+4 = %d\n",*(pMS+4) );
  printf("*pMS+8 = %d\n",*(pMS+8) );
}

The terminal shows bogus values for b and c (at least, I think b and c should be located at pMS+4 and pMS+8):

gcc version 4.6.3

pMS = 1926301980
&a = 1926301980
&b = 1926301984
&c = 1926301988
*pMS = 13
*pMS+4 = 32765
*pMS+8 = 32765

Solution

  • pMS+4 is not the address of the integer located four bytes beyond the start of the structure. Additions to pointers are scaled based on the pointer type so, if it were a pointer to an integer, it would be four integers beyond the start (16 bytes if you have 32-bit ints). See, for example:

    int someInt[2] = {4, 9}; // assume 4-byte int, big-endian
    int *x = &someInt[0];
    
    // | someInt[0] @ 0x1000 | someInt[1] @ 0x1004 |
    // |       0,0,0,4       |       0,0,0,9       |
    // |     x = 0x1000      |     x+1 = 0x1004    |
    // |      *(x) = 4       |      *(x+1) = 9     |
    

    However, it's even worse in your case since your pointer is to the actual structure. That means it's scaling by the size of the entire struct, three complete integers (plus padding if needed).