我有这样的代码
int main ()
{
unsigned int x [4] [3] =
{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};
printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3);
}
所有 3 个值的输出都相同,任何人都可以告诉我为什么。?
正如其他人指出的那样 - 您需要使用正确的格式说明符,并将这些值转换为指针。
现在谈谈为什么它们都赋予相同的价值。
这里 x 是一个数组。并且其元素的类型unsigned int[3]
.即 x
是一个数组的unsigned int[3]
数组。
首先,x + 3
给出数组中第四个元素的地址。那就是{10, 11, 12}
地址 .此数组在内存中的地址将是其在内存中的第一个元素的地址。这是内存中10
的地址。注意这个值是int (*) [3]
的,即 address of an unsigned int[3] array
.
二、* (x + 3)
相当于 x[3],这是第四个元素,即 unsigned int[3]
。它是数组{10, 11, 12}
。此值指向数组{10, 11, 12}
.也就是说,此值指向 10
。请注意,此值为 unsigned int[3]
。
第三*(x+2) + 3
:这里*(x + 2)
相当于x[2]
是unsigned int[3]
,是{7, 8, 9}
数组,当你做一个+ 3
你又得到了10
的地址。请注意,此值为 unsigned int[3]
。
因此,您会看到在所有三种情况下,您的结果都是内存中的相同地址,即存储10
的地址 - 即使您在不同的时间表示不同的事物; 一开始unsigned int (*)[3]
,第二和第三unsigned int[3]
。
提炼的未定义行为:
printf("%u, %u, %u", x + 3, * (x + 3), * (x + 2) + 3);
所有额外的参数都必须unsigned int
,但是 2d 是unsigned int (*)[3]
的,3d 是unsigned int *
的,4 个也是unsigned int *
的。
你得到的值是错误的,因为你的指针算术是错误的。
x
的类型是 unsigned int[4][3]
,一个长度为 4 的数组,其每个成员本身就是一个长度为 3 的数组。
那么什么是x+3
?它是x
中最后一个成员的地址(请记住,x
的成员是数组(。
因此*(x+3)
本身就是一个数组。但是,当您将数组作为函数参数传递时,它们会发生什么?它们衰减成指针。因此,您会看到该数组中第一个元素的地址,该地址被 printf
中的错误类型说明符破坏。
好的,让我们以元素x[2][3]
为例。它将是这种表达*(*(x+2)+3)
完全等同于*(&x[0][0] + 2*3 + 3)
。