C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了将union字段中的位解释为C/C++中的不同数据类型大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图访问Union位作为不同的数据类型.例如:

typedef union {
    uint64_t x;
    uint32_t y[2];
    }test;

    test testdata;
    testdata.x = 0xa;
    printf("uint64_t: %016lx\nuint32_t: %08x %08x\n",testdata.x,testdata.y[0],testdata.y[1]);
    printf("Addresses:\nuint64_t: %016lx\nuint32_t: %p %p\n",&testdata.x,&testdata.y[0],&testdata.y[1]);

输出

uint64_t: 000000000000000a
uint32_t: 0000000a 00000000
Addresses:
uint64_t: 00007ffe09d594e0
uint32_t: 0x7ffe09d594e0 0x7ffe09d594e4

y指向的起始地址与x的起始地址相同.由于两个字段使用相同的位置,x的值不应该是00000000 0000000a吗?

为什么不发生这种情况?内部转换如何在具有不同数据类型的不同字段的联盟中发生?

要做什么来使用联合以与uint64_t中相同的顺序检索精确的原始位作为uint32_t?

编辑:
正如评论中所提到的,C给出了未定义的行为.
它在C中如何工作?我们真的可以这样做吗?

解决方法

我将首先解释您的实现中会发生什么.

您正在uint64_t值和2个uint32_t值的数组之间进行类型惩罚.根据结果​​,您的系统是小端,并且很乐意通过简单地重新解释字节表示来接受类型惩罚.并且0x0a的字节表示为小端uint64_t是:

Byte number  0    1    2    3    4    5    6    7  
Value        0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00

little endian中的最低有效字节具有最低地址.现在很明显为什么uint32_t [2]表示为{0x0a,0x00}.

但是你所做的只是在C语言中是合法的.

C语言:

C11表示为6.5.2.3结构和工会成员:

95)说明明确说:

因此,即使注释不是规范性的,它们的目的是明确标准应该被解释的方式=>代码是有效的,并且在定义uint64_t和uint32_t类型的小端系统上定义了行为.

C语言:

C部分更严格. C17的草案n4659在[basic.lval]中说明:

注释56明确地说:

因为在C标准中从未引用过双关语,并且因为结构/联合部分不包含C的重新解释的等价物,这意味着在C中读取不是最后写入的成员的值会调用undefined行为.

当然,常见的编译器实现编译C和C,并且大多数它们甚至在C源中也接受C语言,因为gcc C编译器很乐意接受C源文件中的VLA.毕竟,未定义的行为包括预期的结果……但是你不应该依赖它来获取可移植的代码.

大佬总结

以上是大佬教程为你收集整理的将union字段中的位解释为C/C++中的不同数据类型全部内容,希望文章能够帮你解决将union字段中的位解释为C/C++中的不同数据类型所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: