【问题标题】:C array address confusionC数组地址混淆
【发布时间】:2009-04-29 08:47:12
【问题描述】:

假设我们有以下代码:

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

【问题讨论】:

标签: c arrays pointers


【解决方案1】:

您必须记住表达式 a[2] 的真正含义。它完全等同于*(a+2)。如此之多,写2[a] 是完全合法的,具有相同的效果。

为了使它起作用并且有意义,指针算术考虑了所指向事物的类型。但这是在幕后处理的。您只需在数组中使用自然偏移量,所有细节都可以解决。

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

在后台,在您的示例中,索引乘以 sizeof(int) 以获得添加到数组基址的字节偏移量。您在两份地址打印件中公开了该详细信息。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 返回值是一个int,不是一个int*。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

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

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

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

          【讨论】:

            【解决方案7】:

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

            一个整数/数字。同理,今天 - 4 月 1 日 = 数字。不是日期

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                猜你喜欢
                • 2014-08-05
                • 2018-07-26
                • 1970-01-01
                • 1970-01-01
                • 2013-09-19
                • 1970-01-01
                • 2012-01-11
                • 2012-12-24
                • 1970-01-01
                相关资源
                最近更新 更多