{{1}}
我的问题是,为什么打印5 0 0 0而不是5 1 2 3?为什么数组"消失了?"
答案 0 :(得分:6)
在你的情况下
A[0] = 5;
将5
写为整数,其大小大于char
(2,4,8,取决于)。
您的系统似乎是小端,因此在第一个char
位置写入5,然后为零。
请注意,如果sizeof(int)
为8(在某些系统上可能会发生),则代码不安全并触发未定义的行为,因为它会覆盖mem
数组之后的内存(更不用说可能导致操作失败的错位问题,甚至某些处理器上的崩溃)
这就是为什么我们必须尊重strict aliasing rule以避免对编译器撒谎,例如,创建一个union
,以便编译器可以调整对齐&检查尺寸。
此其他Q& A相关:What happens when you cast a char * address to int * in C when the address is not word-aligned?
答案 1 :(得分:2)
因为在您的系统中sizeof int
至少是4
的{{1}}倍,所以花费sizeof(char)
个字节来覆盖您写的所有内容,因为4
是一个指向A
的指针。(但它可能需要更大)(这种情况通常是这样)如果不是,则表示未定义的行为。
另请注意,我们如何编写它取决于字节顺序。在你的情况下它是小端。因此,基于字节序,它可能也会有所不同。无论这只不过是实验目的。
另外,为了让您了解当int
大于sizeof(int)
时它是UB的原因 - 那么您将通过4
访问此阵列内存中的一些内容并尝试修改它并对其进行更改 - 导致未定义的行为。
答案 2 :(得分:2)
当您尝试使用char *
指针对int
类型进行别名时,您的代码会显示未定义的行为。这违反了严格的别名规则,因此您的代码就是错误的。
char *
类型可以别名其他指针类型,但不是相反。因此,请确保不要违反语言的限制。
答案 3 :(得分:0)
int* A = (int*)(mem);
- >风险未定义的行为每个“如果
结果指针未正确对齐引用类型,行为未定义。“C11dr§6.3.2.37
所以代码的其余部分没有实际意义。
使用union
来解决对齐和消除锯齿问题。
#include <stdio.h>
int main(void) {
union {
int i;
unsigned char mem[sizeof(int)];
} u;
for (unsigned i = 0; i < sizeof(int); i++) {
u.mem[i] = i;
printf("%hhu\t", u.mem[i]);
}
printf("\n");
u.i = 5;
for (unsigned i = 0; i < sizeof(int); i++) {
printf("%hhu\t", u.mem[i]);
}
printf("\n");
return 0;
}
输出(可能因机器而异)
0 1 2 3
5 0 0 0
原因:现在未定义的行为 UB已从代码中删除, Jean-François Fabre好的答案解释了差异。