我的代码是这样的我的程序的输出是混乱
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个值都相同谁能告诉我为什么?
我的代码是这样的我的程序的输出是混乱
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]
,三维是unsigned int *
,第四是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)
。
使用错误的格式说明符是未定义的行为。 – mch
错误的格式说明符%u是用于unsigned int的。 –
'x + 3'的类型是'unsigned int(*)[3]'(一个指针),'*(x + 3)'和'*(x + 2)+ 3'的类型是'unsigned int *'。所有3个都不是'unsigned int',而是指针,所以你应该使用'%p'并且转换为'(void *)'。 – mch