C数组地址混乱

时间:2009-04-29 08:47:13

标签: c arrays pointers

假设我们有以下代码:

int main(){
    int a[3]={1,2,3};
    printf("      E: 0x%x\n", a);
    printf("  &E[2]: 0x%x\n", &a[2]);
    printf("&E[2]-E: 0x%x\n", &a[2] - a);
    return 1;
}

编译并运行时,结果如下:

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2

我理解& E [2] 的结果是8加上数组的地址,因为索引为2且类型为int(我的32位系统上为4个字节),但我无法弄清楚为什么最后一行是2而不是8?

另外,最后一行应该是什么类型 - 整数或整数指针?

我想知道是否是C型系统(有点投射)才能产生这种怪癖?

8 个答案:

答案 0 :(得分:10)

你必须记住表达式a[2]的真正含义。它完全等同于*(a+2)。这么多,写2[a]代替它是完全合法的,效果相同。

为了使其工作和理解,指针算法会考虑指向的事物的类型。但这在幕后得到了解决。您只需在数组中使用自然偏移量,所有细节都可以解决。

同样的逻辑适用于指针差异,这解释了2的结果。

在引擎盖下,在您的示例中,索引乘以sizeof(int)以获得字节偏移量,该偏移量将添加到数组的基址中。您可以在地址的两个打印件中公开该细节。

答案 1 :(得分:8)

当减去相同类型的指针时,结果是元素数而不是字节数。这是设计使您可以轻松索引任何类型的数组。如果你想要多少字节 - 将地址转换为char *。

答案 2 :(得分:7)

当您将指针递增1(p + 1)时,通过将(p + sizeof(Type))个字节添加到p,指针将指向下一个有效地址。 (如果Type为int,则为p + sizeof(int))

类似的逻辑也适用于p-1(当然在这种情况下减去)。

如果你只是在这里应用这些原则:

简单来说:

a[2] can be represented as (a+2)
a[2]-a      ==>  (a+2) - (a)    ==> 2

所以,在幕后,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2

答案 3 :(得分:5)

线& E [2] -2正在进行指针减法,而不是整数减法。指针减法(当两个指针指向相同类型的数据时)返回地址的差值除以它们指向的类型的大小。返回值是一个int。

要回答“更新”问题,再次执行指针算术(此时指针添加)。它在C中以这种方式完成,以便更容易“索引”指针所指向的一大块连续数据。

答案 4 :(得分:2)

您可能对Pointer Arithmetic In C问题和答案感兴趣。

基本上,+和 - 运算符在指针上使用时会考虑元素大小。

答案 5 :(得分:1)

在C中添加和减去指针时,使用数据类型的大小而不是绝对地址。

如果你有一个int指针并向其添加数字2,它将提前2 * sizeof(int)。以同样的方式,如果你减去两个int指针,你将得到sizeof(int)单位的结果,而不是绝对地址的差异。

(使用数据类型大小的指针非常方便,因此您可以简单地使用p++,而不必每次都指定类型的大小:p+=sizeof(int)。)

答案 6 :(得分:1)

Re:“另外,最后一行的类型应该是什么?一个整数,还是一个整数指针?”

整数/数字。同样的道理:今天 - 4月1日=数字。不是约会

答案 7 :(得分:0)

如果要查看字节差异,则必须使用大小为1字节的类型,如下所示:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))