C中的指针和多维数组

2ledvvac  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(102)

下面是一个C代码:

#include <stdio.h>
int main(void) {
    int a[4][2] = { {1, 2}, {3, 4}, {5, 6}, {7, 8} };

    printf("   a + 2 = %p,    a[2] = %p\n", a + 2,  a[2]);
    printf("   *(a + 2) = %d,     *(a[2]) = %d\n", *(a + 2), *(a[2]));

    return 0;
}

结果是:

a + 2 = 0x7ffc31494b00,    a[2] = 0x7ffc31494b00
   *(a + 2) = 826886912,     *(a[2]) = 5

a + 2a[2]指向同一个地址。为什么解引用后得到两个不同的值?

2q5ifsrm

2q5ifsrm1#

*(a+2)*(a[2])之间的差异是由于a+2a[2]的不同类型以及C将数组自动转换为指针。a+2指向一个数组,*(a+2)是一个数组。a[2]是数组,*(a[2])int
C有一个规则,在表达式中使用的数组会自动转换为指向其第一个元素的指针,除非它是sizeof的操作数,一元&的操作数,或者是用于初始化数组的字符串文字。
所以a + 2被计算:

  • a是一个由四个两个元素组成的数组。
  • 该数组会自动转换为指向其第一个元素的指针,因此结果是&a[0],它是指向两个元素的数组的指针。
  • 添加两个将其调整为指向a中更远的两个元素。
  • 最终结果是&a[2],一个指向两个元素的数组的指针。

a[2]计算:

  • a[2]被指定为等同于*(a+2)
  • a+2如上所述进行计算,得到&a[2],一个指向两个元素的数组的指针。
  • 应用*生成a[2],一个包含两个元素(a[2][0]a[2][1])的数组。
  • 数组自动转换为指向其第一个元素&a[2][0]的指针,该元素是指向int的指针。

printf(" a + 2 = %p, a[2] = %p\n", a + 2, a[2]);中,打印的两个东西是:

  • a+2,我们从上面知道是&a[2]
  • a[2],我们从上面知道是&a[2][0]

这两个地址是内存中同一个点的地址数组a[2]从它的第一个元素a[2][0]开始的同一个位置开始。因此,打印它们打印相同的值也就不足为奇了。(从技术上讲,您应该通过将这些地址转换为void *来打印这些地址,因为%p转换被指定为期望void *参数。
printf(" *(a + 2) = %d, *(a[2]) = %d\n", *(a + 2), *(a[2]));中,打印的两个东西是:

  • *(a + 2)。同样,a + 2&a[2],它是指向两个int的数组的指针。应用*生成该数组。数组会自动转换为指向其第一个元素&a[2][0]的指针。用%d打印这个是一个错误,因为%d被指定为期望int参数,但你已经传递了一个指针。打印的“826886912”是地址31494b0016的十进制表示。(这并不总是结果。C标准没有定义使用%d打印地址时的行为。
  • *(a[2])。从上面看,a[2]&a[2][0]。当应用*时,这会产生a[2][0],即intint的值打印为十进制数字。
b09cbbtk

b09cbbtk2#

  • a + 2执行指针运算,但解引用a,并且它具有指向两个int元素的数组的指针类型
  • a[2]解引用a并具有指向int的指针类型

两者都指向相同的内存位置,但都有 *different类型 *。
a + 2和a[2]指向同一个地址。为什么解引用后得到两个不同的值?

  • 第一个打印的值是一个指向int的指针,它被转换为一个有符号整数
  • 第二个打印的是有符号整数。

a[2]*(a + 2)相同
您需要:

printf("   **(a + 2) = %d,     *(a[2]) = %d\n", **(a + 2), *(a[2]));

相关问题