2011-04-09 135 views
1

试图更好地学习指针数学我写了这段代码。其目的是增加指针投掷结构和打印它的成员。我知道如何打印成员更简单的方法,但真的想知道我的指针数学是如何搞砸的。谢谢。C指针数学结构

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; 
} 

回答

5

指针算法通过指向的字节数递增一个指针。例如,

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

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

因此,你行

address = address + sizeof(int); 

实际上改变addressaddress + sizeof(int) * sizeof(astruct)(使用正常,没有指针运算)。

由于允许编译器在结构中引入填充,所以没有保证的方式来执行所尝试的操作。考虑结构

struct A { 
    char a; 
    int b; 
}; 

编译器将最有可能给这个结构布局如下:

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

所以你不能采取一个结构实例的地址,并添加1

得到 b

在你的特定的情况下,编译器可能是没有引入填充,所以你可以用这些行来更新address

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

此外,虽然,这完全取决于编译器布局的结构,你觉得会的方式,任何微小的变化可能会打破它,所以你真的不应该依赖于这种类型的行为。

+0

并不能保证这两个整数至少是连续的吗? – Alnitak 2011-04-09 15:12:31

+0

该标准使得关于填充的mo保证。 (这就是所有*可能* s的原因) – hugomg 2011-04-09 19:22:10

3

添加到指针时,实际上会添加n * sizeof(*ptr)字节。

因此,在你的结构需要12个字节的32位机器上,添加sizeof(int)字节实际上会将48个字节添加到指针。

要在num2点,你必须先投地址的指针整数

int *iaddress = (int *)address; 

,然后添加一个,要达到你的4567值。

0

该结构旨在避免这种类型的计算。您可以使用mystruct.num,mystruct.num2mystruct.string来代替迭代内存。因为你不为'aaaaaaa'分配内存,所以这仍然是段错误。