union un
{int i;
char c[2];
}x;
main()
{x.c[0]=10;
x.c[1]=1;
printf("%d\n",x.i);
}
这个跟大小端有关,输出010A说明系统使用的是大端,即低地址位存低位,高地址位存高位。
因为字节序,Byte Order,或者叫端序Endian。
常见的字节序有大端序Big Endian和小端序Little Endian两种,x86是典型的小端序架构。小端序下,int存储是低地址存高位,举例而言,0x12345678在小端序下,从低地址向高地址存储顺序就是78 56 34 12。大端序正相反,低地址存低位,0x12345678就是12 34 56 78。还有一种不太常见的PDP端序,是两组两字节构成四字节int,组内小端序组间大端序,那么就是34 12 78 56。
你的代码实际上还暗含一个UB,那就是通过x.c赋值,却在不初始化x.i的情况下访问x.i(没错这是未定义行为,如果编译器的行为是把i字段自动初始化为0,那也是合法的)。我们这里可以假定你的编译器对此的处理方式是非常常见的直接操作同一段内存地址。那么,从低地址到高地址分别是a 1 0 0,按小端序解析(就是要反过来阅读)就是0x0000010a。
端序只和你的机器硬件有关,和C标准无关。
由于你的代码涉及一个未定义行为,一个平台定义行为,因此它的执行结果可以是其他任何数字,甚至printf直接报错也是合法实现。达成你的这个输出的必要前提是:
更正:题主的代码在C和C++下均可编译(g++-10)。根据C++和C的标准,题主的代码未必是UB。C标准明确规定了union中,访问union未初始化字段的具体行为,即为type punning,也是最经典的行为。然而对于C++,标准没有这样的规定,只规定了几种特殊情形,其中题主代码所示的情形属于未定义行为。