C数组地址混乱

Pwn*_*Pwn 11 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;
}
Run Code Online (Sandbox Code Playgroud)

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

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2
Run Code Online (Sandbox Code Playgroud)

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

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

我想知道是不是这种怪癖的C型系统(有点铸造)?

RBe*_*eig 10

你必须记住表达式的a[2]真正含义.它完全等同于*(a+2).因此,2[a]相反的效果是完全合法的.

为了使其有效并且有意义,指针算法会考虑指向的事物的类型.但这在幕后得到了解决.您只需在阵列中使用自然偏移,所有细节都可以解决.

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

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


sha*_*oth 8

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


aJ.*_*aJ. 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
Run Code Online (Sandbox Code Playgroud)

所以,在幕后,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2
Run Code Online (Sandbox Code Playgroud)


mar*_*cog 5

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

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