C 数组地址混淆

C 数组地址混淆,c,arrays,pointers,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

假设我们有以下代码:

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类型系统(类似于强制转换)造成了这种怪癖?

当减去相同类型的指针时,结果是元素数而不是字节数。这是经过设计的,因此您可以轻松地为任何类型的数组编制索引。如果需要字节数-将地址强制转换为char*

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

要回答“更新”问题,再次执行指针运算(这次是指针添加)。在C中这样做是为了更容易“索引”指针指向的连续数据块。

您可能对问答感兴趣


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

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

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

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

如果您有一个int指针,并向其添加数字2,它将前进2*sizeof(int)。同样,如果减去两个int指针,结果将以sizeof(int)为单位,而不是绝对地址之差


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

当您将指针增加1(p+1)时,指针将通过添加(p+sizeof(type))指向下一个有效地址)字节到p。(如果类型为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

您必须记住表达式
a[2]
的真正含义。它完全等同于
*(a+2)
。因此,以同样的效果编写
2[a]
是完全合法的

为了让它起作用并有意义,指针算法考虑了指向的对象的类型。但这是在幕后处理的。只需在数组中使用自然偏移,所有细节都会得到解决

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

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

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


整数/数字。同样的道理:今天-4月1日=数字。not date

返回值是一个int,而不是int*。这几乎是printf的重复(“E:0x%x\n,&a);