下面是一个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 + 2
和a[2]
指向同一个地址。为什么解引用后得到两个不同的值?
2条答案
按热度按时间2q5ifsrm1#
*(a+2)
和*(a[2])
之间的差异是由于a+2
和a[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]
,即int
。int
的值打印为十进制数字。b09cbbtk2#
a + 2
执行指针运算,但不解引用a
,并且它具有指向两个int
元素的数组的指针类型a
并具有指向int
的指针类型两者都指向相同的内存位置,但都有 *
different
类型 *。a + 2和a[2]指向同一个地址。为什么解引用后得到两个不同的值?
a[2]
与*(a + 2)
相同您需要: