免责声明:OP的标签很模糊,所以这个答案使用代码作为参考框架,即C++(使用iostream
,拉入std
命名空间,cout
)。
您正在union
以不适当的方式使用。但我们稍后再谈。
e.i = 20;
您的代码首先使用 union as i
,一个整数。没关系。但是你后来的所作所为真的不是一个好主意。首先,您做了两件可以接受的事情:
cout << &e.j;
cout << &e.i;
您在 union 中查询了两个int
s 的地址,这很好,因为它们都共享存储,因此第一个字节的地址是共享的。
cout << &e.c[0]; //Why can't I print this address
cout << e.c[1]; // Why can't I print this value
现在,这就是你越界的地方。您现在正在执行隐式指针算术和取消引用,以索引到char[]
数组,即使您尝试获取第一个元素的地址,也可能评估一个不是联合中最后一个集合的元素。所以,这是一个很大的禁忌。
此外,&e.c[0]
基本上是char*
哪个将被“拦截”并被cout
视为 C 风格的字符串。它不会将其视为简单地址。
cout << e.c[1]; // Why can't I print this value
未定义的行为。“可是,可是!” ,我能听到你们中的一些人说。是的,它是 C++ 中的 UB。在 C99 (6.5/7) 中有效,仅通过脚注和一些胶带。这是一件简单的事情,LightnessRacesInSpace 和 Mysticial 在这个答案和其他人的评论中已经解释过。
是的,您可以将任何类型的变量转换为 char 数组,并出于您的任何目的而将其弄乱。但是在 C++ 中通过联合进行类型双关是非法的,没有任何理由和借口。是的,它可能会起作用。是的,如果您不介意,您可以继续使用它。但根据 C++ 标准,这显然是非法的。
除非该成员是您为其分配值的联合的最后一个成员,否则您不得检索其值。就这么简单。
C++ 中的联合有一个目的,如下所述。它们还可以具有成员函数和访问说明符。它们不能有虚函数或静态成员。它们也不能用作基类或从某些东西继承。而且它们不能用于类型双关语。这在 C++ 中是非法的。
进一步阅读!
了解工会
工会是:
工会不是:
- 一种在工会元素之间进行牛仔表演的方法
- 一种欺骗严格别名的方法。
甚至 MSDN 都做对了:
联合是一种用户定义的数据或类类型,在任何给定时间,它只包含其成员列表中的一个对象(尽管该对象可以是数组或类类型)。
这是什么意思?这意味着您可以按照以下方式定义一些东西:
union stuff {
int i;
double d;
float f;
} m;
这个想法是所有这些都坐在内存中的同一个空间中。联合的存储是从给定实现中的最大数据类型推断出来的。平台在这里有很大的自由度。规范无法涵盖的自由。不是 C。不是 C++。
您不能将其作为 an 写给 union int
,然后将其作为 a float
(或其他任何东西)作为某种奇怪的牛仔 reinterpret_cast 的一种方式来阅读。
的使用std::cout
是出于示例目的和简单性。
这是非法的:
m.i = 5;
std::cout << m.f; // NO. NO. NO. Please, no.
这是合法的:
m.i = 5;
std::cout << m.i;
// Now I'm done with i, I have no intention of using it
// If I do, I'll make sure I properly set it.
m.f = 3.0f;
std::cout << m.f; // No "cowboy-interpreting", defined.
// I've got an idea, but I need it to be an int.
m.i = 3; // m.f and m.d are here-by invalidated.
int lol = 5;
m.i += lol;
注意没有“交叉火力”。这是预期的用途。用于三个不同时间使用的三个变量的超薄内存存储,无需争吵。
误解是如何产生的?一些非常糟糕的人有一天醒来,我敢打赌其中一个是 3D 程序员并考虑这样做:
// This is wrong on so many different levels.
union {
float arr[4];
struct {
float x,y,z,w;
};
};
毫无疑问,他有一个“高尚的想法”,即以浮点数组和单个 xyzw 成员的形式访问 4 元组。现在,您知道为什么在联合方面这是错误的,但这里还有一个失败:
C++ 没有匿名结构。它确实具有匿名联合,出于上述目的,使其更接近预期用途(删除m.
“前缀”),因为您肯定可以看到这对联合背后的一般理念有何好处。
不要这样做。请。