【问题标题】:Why do I get different results for "a+1" and "&a+1" in a 2d array? [duplicate]为什么我在二维数组中得到“a+1”和“&a+1”的不同结果? [复制]
【发布时间】:2020-08-06 06:59:13
【问题描述】:
#include<stdio.h>
#include<conio.h>

int main()
{
    int a[3][4] = {1, 2, 3, 4, 4, 3, 2, 1, 7, 8, 9, 0};
    clrscr();    
    printf("%u \n",a);
    printf("%u, %u\n", a+1, &a+1);
    getch();
    return 0;
}

输出: 65502 65510 65526

如果sizeof(int)=2 和基地址是65502,这个程序如何工作?

【问题讨论】:

  • 因为a+1 表示将1 sizeof *a 添加到a,而&amp;a+1 表示将1 sizeof a 添加到&amp;asizeof *asizeof (int[4])sizeof asizeof (int[3][4])
  • 打印带有%u 的指针是未定义的行为。
  • 我认为这对您的帮助最大。读一读。 stackoverflow.com/a/4608421/10758654

标签: arrays c pointers


【解决方案1】:

当你在表达式中使用像a 这样的数组时,它通常会经历“指针衰减”,这意味着你会得到一个指向数组第一个元素的指针。

所以,a 的类型为 int[3][4],并衰减为 int (*)[4]。当你写a+1时,你会得到a[1]的地址……这是sizeof(*a)a之后的字节,即sizeof(int)*4,在你的系统上是8。

当您使用&amp; 时,不会发生指针衰减。 &amp;a 不是一个数组(它已经是一个指针),所以当你写&amp;a+1 时,你会得到a 的“一个过去”的地址……这是sizeof(a) 在a 之后的字节,即@ 987654335@,或系统上的 24 个字节。

请注意,严格来说,打印指针的正确方法是使用%p

printf("%p\n", a);
printf("%p, %p\n", a+1, &a+1);

(从技术上讲,您还必须转换为 char *void *,但这并不重要。)

【讨论】:

    【解决方案2】:
    printf("%u, %u\n", a+1, &a+1);
    
    • a+1 - 这里a 衰减为指向其第一个元素的指针。在这种情况下,指向4int(类型int (*)[4])的数组的指针。请查看What is array to pointer decay? 了解更多信息。

      此后,您将此指针加一。因此,现在获得的地址是二维数组正向的4int 的一个数组元素之一,它与您的输出匹配为sizeof(int) == 2 * 4 = 86550265510 的区别是8


    • &amp;a+1 - 首先评估&amp;a。当应用&amp; 运算符时,a 不会衰减为指向其第一个元素的指针。而是&amp;a 获得一个指向整个二维数组的指针/一个指向由 3 个数组组成的数组的指针,该数组由 4 个 int 组成(类型为 int (*)[3][4])。

      将此指针递增一可以使您获得整个二维数组的大小,这也与您的输出相匹配,因为65502 65526 之间的差异是24,这是正确的,因为sizeof(int) == 2 * (@987654349 @) = 24(3 * 4) 是二维数组中元素的数量。


    注意:打印带有%u 格式说明符的指针会调用严格意义上的undefined behavior。您需要为指针使用 %p 格式说明符,并且需要将指针参数强制转换为 void * 以符合标准。

    printf("%p\n", (void*) a);
    printf("%p, %p\n", (void*) a+1, (void*) &a+1);
    

    【讨论】:

      【解决方案3】:

      当你增加一个指针时,它会以指针可以指向的对象大小为单位增加

      a 的类型是int (*)[4]1),即指向一个对象的指针,该对象是一个4int 类型的数组。因此,a + 1 将是通过将 4 整数数组的大小与表达式中从 a 评估的指针相加而获得的指针。

      &amp;a 的类型是int (*)[3][4]1),即指向一个对象的指针,该对象是一个二维数组int,维度为3x4。因此,&amp;a + 1 将是一个指针,它是通过将维度为 3x4 的二维整数数组的大小与表达式中从 &amp;a 评估的指针相加而获得的。


      1. 当您访问一个数组时,它会被转换为一个指向第一个元素的指针(很少有exceptions 符合这条规则)。

      【讨论】:

        猜你喜欢
        • 2017-01-30
        • 1970-01-01
        • 1970-01-01
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 1970-01-01
        相关资源
        最近更新 更多