使用带有联合的类型双关语的问题
Posted
技术标签:
【中文标题】使用带有联合的类型双关语的问题【英文标题】:Issue using Type Punning with union 【发布时间】:2019-11-20 17:07:48 【问题描述】:我想了解有关类型双关语和别名的更多信息。所以我使用GCC documentation 在选项-fstric-aliasing
提供的代码,如下所示:
union a_union
int i;
double d;
;
int f()
union a_union t;
t.d=3.0;
return t.i
/*what I add*/
int main(int argc, char *argv[])
printf("%d\n",f());
return 0;
我期望没有什么特别的,但我只得到 0。所以我测试了 t.d
的不同值,但没有变化。
我在 Debian 9 上使用 gcc 6.3 测试此代码,没有选项。
我也尝试使用选项-fno-strict-aliasing
相同的结果
如果有人可以解释一下,为什么我只得到 0 那就太好了
【问题讨论】:
您的代码中有a_union
和q_union
。这实际上是您的代码,还是您在复制粘贴时出错了?
哦,那是因为我用了两台电脑,一台是azerty键盘,另一台是qwerty,所以有时我会出错
【参考方案1】:
这取决于您的特定处理器使用的存储类型。
3.0000000000000000(双精度3)用4008 0000 0000 0000(十六进制)表示
您的处理器可以按各种顺序存储浮点数,其中一些首先存储最低有效字节/字。在这种情况下,int 只会返回 0000 0000。
尝试使用 Pi 或 sqrt(2)
【讨论】:
【参考方案2】:成员的大小在任何常见系统中都不匹配。 int
现在通常是 32 位,double
是 64 位。由于采用 little-endian 存储,3.0000000000
末尾的零位对应于 int
成员的零位。
试试这个:
#include <inttypes.h>
#include <stdio.h>
union q_union
uint64_t i;
double d;
;
_Static_assert(sizeof (union q_union).i == sizeof (union q_union).d,
"The sizes of double and uint64_t must match");
uint64_t f(void)
union q_union t;
t.d = 3.0;
return t.i;
int main(int argc, char *argv[])
printf("%" PRIu64 "\n", f());
printf("%#" PRIx64 "\n", f());
return 0;
输出:
4613937818241073152
0x4008000000000000
【讨论】:
【参考方案3】:具有3.0
值的double
有很多0 字节。我假设你的机器的字节序是这样的,它们与 int 重叠。如果您使用的是3.1
而不是3.0
,您应该会看到另一个值。
除了int
,您也可以尝试使用unsigned long long
,它通常具有与双精度相同的大小,您将能够打印其整个表示。
【讨论】:
以上是关于使用带有联合的类型双关语的问题的主要内容,如果未能解决你的问题,请参考以下文章
是否通过 C99 中未指定的联合进行类型双关,并且它是否已在 C11 中指定?