我读到结构中位字段的顺序是特定于平台的.如果我使用不同的特定于编译器的打包选项,这将保证数据在写入时以正确的顺序存储吗?例如:
struct Message
{
unsigned int version : 3;
unsigned int type : 1;
unsigned int id : 5;
unsigned int data : 6;
} __attribute__ ((__packed__));
Run Code Online (Sandbox Code Playgroud)
在具有GCC编译器的英特尔处理器上,字段在显示时显示在内存中.Message.version是缓冲区中的前3位,然后Message.type是.如果我找到各种编译器的等效结构包装选项,这将是跨平台的吗?
Stack Overflow问题的一些答案获取浮点数的IEEE单精度位建议使用union类型双关的结构(例如:将a的位float转换为a uint32_t):
union {
float f;
uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;
Run Code Online (Sandbox Code Playgroud)
但是,uint32_t根据C99标准(至少草案n1124),联盟成员的值似乎未指定,其中第6.2.6.1.7节规定:
当值存储在union类型的对象的成员中时,对象表示的字节与该成员不对应但与其他成员对应的字节采用未指定的值.
C11 n1570草案至少有一个脚注似乎暗示不再是这种情况(见6.5.2.3中的脚注95):
如果用于读取union对象的内容的成员与上次用于在对象中存储值的成员不同,则将值的对象表示的适当部分重新解释为新类型中的对象表示形式在6.2.6中描述(一个过程有时被称为''punning'').这可能是陷阱表示.
但是,第C.6.6.1.7节中的案文与C11草案中的C99草案相同.
这种行为在C99下实际上是未指定的吗?它是否在C11中指定?我意识到大多数编译器似乎都支持这一点,但是知道它是在标准中指定还是只是一个非常常见的扩展会很好.
请解释之间有什么区别union和std::variant为什么 std::variant引入标准?我们应该在什么情况下使用std::variant旧学校union?
你有任何恐怖故事要讲吗?GCC手册最近添加了一个关于-fstrict-aliasing的警告并通过联合转换指针:
[...]获取地址,强制生成指针并取消引用结果具有未定义的行为 [强调添加],即使转换使用了联合类型,例如:
union a_union {
int i;
double d;
};
int f() {
double d = 3.0;
return ((union a_union *)&d)->i;
}
Run Code Online (Sandbox Code Playgroud)
有没有人有一个例子来说明这种未定义的行为?
请注意,这个问题不是关于C99标准所说或不说的.它是关于gcc和其他现有编译器的实际功能.
我只是猜测,但一个潜在的问题可能在于设置d为3.0.因为d是永远不会直接读取的临时变量,并且永远不会通过"稍微兼容"的指针读取,所以编译器可能不会费心去设置它.然后f()将从堆栈中返回一些垃圾.
我的简单,天真,尝试失败了.例如:
#include <stdio.h>
union a_union {
int i;
double d;
};
int f1(void) {
union a_union t;
t.d = 3333333.0;
return t.i; // gcc manual: 'type-punning is allowed, provided...' (C90 6.3.2.3)
}
int f2(void) {
double d = 3333333.0;
return ((union a_union *)&d)->i; // gcc …Run Code Online (Sandbox Code Playgroud) 我需要定义一个这样的类:
class Color
{
private:
union Data
{
unsigned int intValue;
unsigned char argbBytes[4];
}
private:
Data m_data;
};
Run Code Online (Sandbox Code Playgroud)
另一种方法当然是将数据定义为整数,并在必要时将其转换为char数组.
我想知道哪一个是首选方式.这里的矛盾是,我有远程记忆,有人提醒不再使用联合,但在这种情况下它似乎是一个更清洁的解决方案.
我收集unrestricted unions了C++ 11中提出的功能之一.任何人都可以解释这背后的语义及其提供的优势吗?
我正在阅读O'Reilly的Practical C Programming一书,并阅读了关于C编程语言的K&R书籍,而且我在掌握工会背后的概念时遇到了麻烦.
它们采用最大数据类型的大小来构建它们......最近分配的数据会覆盖其余数据......但为什么不根据需要使用/释放内存?
这本书提到它用于通信,你需要设置相同大小的标志; 并且在google网站上,它可以消除奇数大小的内存块......但它是否适用于现代的非嵌入式内存空间?
你可以用它和CPU寄存器做些狡猾的事吗?它只是一个早期编程时代的延续吗?或者它是否像臭名昭着的goto一样,仍然有一些强大的用途(可能在紧凑的内存空间中),这使它值得保持?
我发现下面的代码,它计算log2的float x:
union { float f; unsigned int i; } vx = { x };
float y = vx.i;
y *= 1.0 / (1 << 23);
y = y - 126.94269504f;
return y;
Run Code Online (Sandbox Code Playgroud)
funion 的参数初始化为输入x然后使用i?我无法理解它是如何使用未初始化的东西的.vx.i实际上有什么价值?谢谢.
假设我有一个这样的联盟:
union checkUnion{
std::string* str;
bool someBool;
int aNumber;
};
Run Code Online (Sandbox Code Playgroud)
我如何检查在程序中选择了这 3 个项目中的哪一个?我想对每个项目进行单独的 if 查询。
例如:[伪代码]
if (checkUnion == string)
{
//CODE
}
if (checkUnion == bool)
{
//DIFFERENT CODE
}
Run Code Online (Sandbox Code Playgroud) c++ ×6
unions ×6
c ×5
bit ×1
c++11 ×1
c++17 ×1
c11 ×1
c99 ×1
endianness ×1
gcc ×1
if-statement ×1
logarithm ×1
type-punning ×1