Hap*_*tal 14 c endianness unions
union test
{
int i;
char ch;
}t;
int main()
{
t.ch=20;
}
Run Code Online (Sandbox Code Playgroud)
假设sizeof(int)==2
并且让分配给t的内存地址是2000,2001.
然后在哪里20即t.ch
存储 - 在2000或2001或依赖于机器的字节顺序?
Mat*_*lia 20
C99标准(§6.7.2.1.14)说:
联合的大小足以包含其最大的成员.最多一个成员的值可以随时存储在union对象中.指向适当转换的联合对象的指针指向其每个成员(或者如果成员是位字段,则指向它所在的单元),反之亦然.
(重点补充)
粗体声明实际上说联盟的每个成员都有相同的地址,因此它们都在同一地址"开始".t
作为t.ch
如t.i
,应在地址2000,从而t.ch
重叠用的第一个字节(按地址顺序)t.i
.
在现实世界中,"如果我t.i
在设置之后尝试阅读,我会得到什么"这意味着什么t.c
取决于平台的字节顺序,并且当您在另一个中写入时尝试读取联盟成员的事实取决于未指定的行为. C标准(§6.2.6.1.6/ 7,重述于§J.1.1).
什么有助于理解机器的字节顺序(至少,我认为理解它更直接)是有这样的联合:
union
{
int i;
unsigned char ch[sizeof(i)];
} t;
Run Code Online (Sandbox Code Playgroud)
干
t.i=20;
Run Code Online (Sandbox Code Playgroud)
然后看看两个字符里面的内容t.ch
.如果你是一个little-endian的机器上,你会得到t.ch[0]==20
和t.ch[1]==0
,如果你是一个big-endian的机器(如果在对面sizeof(int)==2
).请注意,正如已经说过的,这是一个特定于实现的细节,标准甚至没有提到字节序.
为了使它更清晰:如果你有一个2字节的int
var设置为20,在little-endian机器上,以地址顺序转储与它相关的内存,你将获得(以十六进制表示,按空格分割的字节) :
14 00
Run Code Online (Sandbox Code Playgroud)
而在大端机器上,你会得到
00 14
Run Code Online (Sandbox Code Playgroud)
从我们的观点来看,big-endian表示看起来"更正确",因为在小端表示中,构成整体的字节int
以相反的顺序存储.
而且我说如果我这样做:
int a=20;
printf("%d",* (char*)&a);
Run Code Online (Sandbox Code Playgroud)
然后输出不依赖于endian-ness,即20是存储在2000还是2001?
是的,在这里确实如此,但在你的问题中,你会问另一件事; 这看起来更像我的榜样.