C pointer math with structures

时光总嘲笑我的痴心妄想 提交于 2019-11-28 06:20:05

问题


Trying to learn pointer math better I wrote this code. The intention was to increment the pointer threw the structure and print it's members. I know how to print it's member easier ways but would really like to know how my pointer math is messed up. Thank you.

typedef struct{ 
  int num;
  int num2;
  char *string;
} astruct ;

int main (int argc, const char * argv[])
{
  astruct mystruct = { 1234, 4567,"aaaaaaa"};

  astruct *address;
  address = &mystruct;

  // this does print 1234
  printf("address 0x%x has value of:%i\n",address, *address); 
  address = address + sizeof(int);

  //this does NOT print 4567
  printf("address 0x%x has value of:%i\n",address, *address); 
  address = address + sizeof(int);

  //this crashes the program, I wanted to print aaaaaaaa
  printf("address 0x%x has value of:%s\n",address, **address); 

  return 0;
}

回答1:


Pointer arithmetic increments a pointer by the number of bytes pointed to. For example,

int a[2];
int *p = a;

assert( &a[0] == p )
assert( &a[1] == p + 1 )

Therefore, your line

address = address + sizeof(int);

actually changes address to address + sizeof(int) * sizeof(astruct) (using normal, not pointer arithmetic).

There is no guaranteed way to do what you are trying, because the compiler is allowed to introduce padding in a struct. Consider the struct

struct A {
    char a;
    int b;
};

The compiler will most likely give this struct the following layout:

+------------+-------------------+-------------+
| a (1 byte) | (3 bytes padding) | b (4 bytes) |
+------------+-------------------+-------------+

So you cannot get to b by taking the address of a struct instance and adding 1.

In your specific case, the compiler probably doesn't introduce padding, so you may be able to use these lines to update address:

address = (char *) address + sizeof(int); // OR...
address = (int *) address + 1;

Again, though, this depends entirely on the compiler laying out the struct the way you think it will, and any small change will probably break it, so you really shouldn't rely on this type of behavior.




回答2:


When you add to a pointer, you actually add n * sizeof(*ptr) bytes.

Hence on a 32 bit machine where your structure would take 12 bytes, adding sizeof(int) bytes would actually add 48 bytes to the pointer.

To point at num2 you would first have to cast address to a pointer to an integer:

int *iaddress = (int *)address;

and then add one to that to reach your 4567 value.




回答3:


The structures are designed to avoid such types of caluculation. Instead of iterating through memory, you can use mystruct.num, mystruct.num2 and mystruct.string. And still this will be a segfault since you do not allocate memory for 'aaaaaaa'.



来源:https://stackoverflow.com/questions/5605745/c-pointer-math-with-structures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!