简体   繁体   English

C数组地址混乱

[英]C array address confusion

Say we have the following code: 假设我们有以下代码:

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

When compiled and run the results are follows: 编译并运行时,结果如下:

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

I understand the result of &E[2] which is 8 plus the array's address, since indexed by 2 and of type int (4 bytes on my 32-bit system), but I can't figure out why the last line is 2 instead of 8? 我理解&E [2]的结果是8加上数组的地址,因为索引为2并且类型为int(我的32位系统上是4个字节),但我无法弄清楚为什么最后一行是2而不是8?

In addition, what type of the last line should be - an integer or an integer pointer? 另外,最后一行应该是什么类型 - 整数或整数指针?

I wonder if it is the C type system (kinda casting) that make this quirk? 我想知道是不是这种怪癖的C型系统(有点铸造)?

You have to remember what the expression a[2] really means. 你必须记住a[2]真正含义。 It is exactly equivalent to *(a+2) . 它完全等同于*(a+2) So much so, that it is perfectly legal to write 2[a] instead, with identical effect. 这么多,写2[a]代替完全合法,效果相同。

For that to work and make sense, pointer arithmetic takes into account the type of the thing pointed at. 为了使其有效并且有意义,指针算法会考虑指向的事物的类型。 But that is taken care of behind the scenes. 但这在幕后得到了解决。 You get to simply use natural offsets into your arrays, and all the details just work out. 您只需在阵列中使用自然偏移,所有细节都可以解决。

The same logic applies to pointer differences, which explains your result of 2 . 相同的逻辑适用于指针差异,这解释了您的结果2

Under the hood, in your example the index is multiplied by sizeof(int) to get a byte offset which is added to the base address of the array. 在引擎盖下,在您的示例中,索引乘以sizeof(int)以获取字节偏移量,该偏移量将添加到数组的基址中。 You expose that detail in your two prints of the addresses. 您在两个地址打印中公开该细节。

When subtracting pointers of the same type the result is number of elements and not number of bytes. 当减去相同类型的指针时,结果是元素数而不是字节数。 This is by design so that you can easily index arrays of any type. 这是设计使您可以轻松索引任何类型的数组。 If you want number of bytes - cast the addresses to char*. 如果你想要字节数 - 将地址转换为char *。

When you increment the pointer by 1 (p+1) then pointer would points to next valid address by adding ( p + sizeof(Type)) bytes to p. 当您将指针递增1(p + 1)时,通过将(p + sizeof(Type))个字节添加到p,指针将指向下一个有效地址。 (if Type is int then p+sizeof(int)) (如果Type为int,则p + sizeof(int))

Similar logic holds good for p-1 also ( of course subtract in this case). 类似的逻辑也适用于p-1(当然在这种情况下减去)。

If you just apply those principles here: 如果你只是在这里应用这些原则:

In simple terms: 简单来说:

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

So, behind the scene, 所以,在幕后,

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

The line &E[2]-2 is doing pointer subtraction, not integer subtraction. 线&E [2] -2正在进行指针减法,而不是整数减法。 Pointer subtraction (when both pointers point to data of the same type) returns the difference of the addresses in divided by the size of the type they point to. 指针减法(当两个指针指向相同类型的数据时)返回地址的差值除以它们指向的类型的大小。 The return value is an int. 返回值是一个int。

To answer your "update" question, once again pointer arithmetic (this time pointer addition) is being performed. 要回答“更新”问题,再次执行指针算术(此时指针添加)。 It's done this way in C to make it easier to "index" a chunk of contiguous data pointed to by the pointer. 它在C中以这种方式完成,以便更容易“索引”指针指向的一大块连续数据。

You may be interested in Pointer Arithmetic In C question and answers. 您可能对Pointer Arithmetic In C的问题和答案感兴趣。

basically, + and - operators take element size into account when used on pointers. 基本上,+和 - 运算符在指针上使用时会考虑元素大小。

When adding and subtracting pointers in C, you use the size of the data type rather than absolute addresses. 在C中添加和减去指针时,使用数据类型的大小而不是绝对地址。

If you have an int pointer and add the number 2 to it, it will advance 2 * sizeof(int). 如果你有一个int指针并向其添加数字2,它将前进2 * sizeof(int)。 In the same manner, if you subtract two int pointers, you will get the result in units of sizeof(int) rather than the difference of the absolute addresses. 以同样的方式,如果你减去两个int指针,你将得到sizeof(int)单位的结果,而不是绝对地址的差异。

(Having pointers using the size of the data type is quite convenient, so that you for example can simply use p++ instead of having to specify the size of the type every time: p+=sizeof(int) .) (使用数据类型大小的指针非常方便,因此您可以简单地使用p++而不必每次都指定类型的大小: p+=sizeof(int) 。)

Re: "In addtion,what type of the last line should be?An integer,or a integer pointer??" Re:“另外,最后一行的类型应该是什么?一个整数,还是一个整数指针?”

an integer/number. 整数/数字。 by the same token that the: Today - April 1 = number. 同样的道理:今天 - 4月1日=数字。 not date 不是约会

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM