使用联合类型成员时的奇怪输出 [英] Strange output when using union type members

查看:30
本文介绍了使用联合类型成员时的奇怪输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码:

#include<stdio.h>

union U{
    int x;
    char y;
};

int main()
{
    union U u1;
    u1.x = 258;
    u1.y = '0';
    printf("%d%d",u1.x,u1.y);
    return 0;
}

奇怪的是,输出是30448.

有人能解释一下这是怎么发生的吗?

Can someone please explain how this happens?

推荐答案

您可能误解了 union 的用途.它意味着一次只存储一个变量,但这个变量可以有多种类型.存储的最后一个变量将覆盖前一个.

You maybe missunderstanding the purpose of a union. It is meant to store only one variable at a time, but this variable can have multiple types. The last variable stored will overwrite the previous.

在您的情况下 u1.y(即 '0',需要提醒的是 '0''0' 的 1 字节 ASCII 十进制表示code> 是 48),是存储的最后一个值,这对应于您打印 '0' 时输出的最后 2 位数字,其 ASCII 十进制表示.

In your case u1.y (which is '0', it's relevant to remind that the 1 byte ASCII decimal representation for '0' is 48), is the last value stored, this corresponds to last 2 digits of your output as you print '0' by its ASCII decimal representation.

对于输出的第一部分,请注意您覆盖了 int 变量 258,它大概是 4 个字节(但为了便于解释,我假设它是 2 个字节)和 1 个字节宽的 char 变量 48.

As for the first part of the output, note that you overwrite the int variable 258, which is presumably 4 bytes (but for the sake of explanation I will assume it's 2 bytes) with the 1 byte wide char variable 48.

258 的二进制值(假设 2 个字节宽 int)是:

The binary value for 258 (assuming 2 bytes wide int) is:

|0|0|0|0|0|0|0|1|0|0|0|0|0|0|1|0|

|   2nd byte    |   1st byte    |              

48(1 字节宽的 char 变量)的二进制值是:

The binary value for 48 (1 byte wide char variable) is:

| | | | | | | | |0|0|1|1|0|0|0|0|

                |   1st byte    | 

当你用一个字节变量覆盖两个字节的联合变量时,只有 8 个最低有效位(最低有效字节)会被覆盖,所以你最终会得到:

When you overwrite the two byte union variable with a one byte variable only the 8 least significant bits(least significant byte) will be overwritten, so you'll end up with:

|0|0|0|0|0|0|0|1|x|x|x|x|x|x|x|x|
| | | | | | | | |0|0|1|1|0|0|0|0|

|0|0|0|0|0|0|0|1|0|0|1|1|0|0|0|0|

这是304的二进制表示.

所以你的代码首先打印 2 字节宽(为了示例)int 304 然后是 1 字节宽 int48('0' 的 ASCII int 表示),因此输出 30448.

So yor code first prints the 2 bytes wide (for the sake of the examle) int 304 and next the 1 byte wide int 48 (the ASCII int representation of '0'), hence the output 30448.

请注意,此行为并非未定义.

Note that this behavior is not undefined.

ISO/IEC 9899:2017 N2176

97) 如果用于读取联合对象内容的成员与上次用于存储值的成员不同在对象中,值的对象表示的适当部分被重新解释为新类型中的对象表示,如 6.2.6 中所述(有时称为类型双关"的过程).这可能是一个陷阱表示.

§ 6.5.2.3

97) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning"). This might be a trap representation.

6 - 当一个值存储在结构或联合类型的对象中时,包括在成员对象中,对应于任何填充字节的对象表示的字节采用未指定的值.51) 结构或联合对象的值永远不是陷阱表示,即使结构或联合对象的成员的值可能是陷阱表示.

6 - When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.51) The value of a structure or union object is never a trap representation, even though the value of a member of the structure or union object may be a trap representation.

7 - 当一个值存储在联合类型对象的成员中时,不对应于该成员但对应于该成员的对象表示的字节其他成员采用未指定的值.

为了确认,您可以使用:

For confirmation you can use:

printf("%p %p\n", (void*)&u1.x, (void*)&u1.y);

这将打印 u1.xu1.y 的内存地址,你不会惊讶地发现它们是相同的.

This will print the memory address of both u1.x and u1.y and you will not be shocked to find that they are the same.

这篇关于使用联合类型成员时的奇怪输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆