寻求 C Union 的明确性
typedef union {
float flts[4];
struct {
GLfloat r;
GLfloat theta;
GLfloat phi;
GLfloat w;
};
struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
};
} FltVector;
好的,所以我想我知道如何使用它,(或者,这就是我看到它的使用方式)即。
FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
float aaa = fltVec1.x;
etc.
但我并没有真正了解工会声明了多少存储空间(4 个浮点数?8 个浮点数?12 个浮点数?),怎么样?为什么?另外为什么在使用 FltVector {{}} 时需要两组花括号?
为什么要使用工会?为什么不做..
struct FltVector {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
}
?
非常感谢任何指点(抱歉双关语)
typedef union {
float flts[4];
struct {
GLfloat r;
GLfloat theta;
GLfloat phi;
GLfloat w;
};
struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
};
} FltVector;
Ok, so i think i get how to use this, (or, this is how i have seen it used) ie.
FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
float aaa = fltVec1.x;
etc.
But i'm not really groking how much storage has been declared by the union (4 floats? 8 floats? 12 floats?), how? and why? Also why two sets of curly braces when using FltVector {{}}?
Why use a union at all? Why not do..
struct FltVector {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
}
?
Any pointers much appreciated (sorry for the pun)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果 sizeof(GLfloat) == sizeof(float) 则已分配 4 个浮点数。
flts[0]
、r
和x
在这里都引用同一块内存。在联合中,联合中声明的每个不同变量都引用同一块内存。
这里我们有 3 个变量、2 个结构体和一个数组,每个变量都从内存中的同一点开始。
if
sizeof(GLfloat) == sizeof(float)
then, 4 floats have been allocated.flts[0]
,r
andx
will all refer to the same piece of memory here.In a union, every different variable declared in the union refers to the same piece of memory.
Here we have 3 variables, 2 structs and an array, and each of them start at the same point in memory.
联合允许您为不同类型的变量“回收”同一内存区域。一般来说,联合占用的存储空间与其最大的单个成员一样多,在本例中可能是 4 个浮点数。您可以使用
sizeof
进行检查。在这种情况下,联合可能用于提供 1) 结构中相同浮点的替代名称(例如
x
和r
共享相同的内存),以及 2) 访问到相同四个浮点数作为数组(例如x
和flts[0]
共享相同的内存)。有时,联合用于各种“黑客”(通常是不可移植的)中,以访问某些数据类型的内部结构,例如机器顺序中整数中的各个字节。A union allows you to “recycle” the same area of memory for different types of variables. Generally the union takes as much storage as its single largest member, in this case probably 4 floats. You can check with
sizeof
.In this case the union is probably used to provide 1) alternative names for the same floats in the struct (e.g.
x
andr
share the same memory), and 2) access to the same four floats as an array (e.g.x
andflts[0]
share the same memory). Sometimes unions are used in various “hacks”, usually non-portable, to access the internals of some data type e.g. the individual bytes in an integer in the machine order.有几个问题:)
@Arkku 关于尺寸的说法是正确的。对齐也可以发挥作用,但可能不是在这里。
为什么这是真的,因为在任何给定时间,并集仅保留可能值之一。出于这个原因,通常将联合放在一个结构中,旁边放置一些标识哪个值有效的东西(有时称为可区分联合或scrim)。
一对大括号用于联合,另一对用于数组初始化器。
A few questions there :)
@Arkku is right about the size. Alignment can also play a part, but probably not here.
Why this is true is that at any given time the union only holds one of the possible values. For this reason it's common to have the union in a struct alongside something which identifies which value is valid (sometimes called a discriminated union or scrim).
One pair of braces is for the union, and the other for the array initalizer.
看整行,
FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
您正在初始化联合中第一个结构体中的四个浮点数。正如您从粗体“in”中看到的,有两层嵌套。如果嵌套层次更深,甚至可以有更多的花括号。
Look at the whole line,
FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
You're initializing the four floats in the first struct in the union. As you can see from the bold "in"s, there are two levels of nesting. If the level of nesting was even deeper, you could even have more curly braces.
在您的示例中,如果我们考虑变量的名称,则联合肯定不会用于通过 x 和 r 访问相同的内存单元(因为半径和 x 坐标不太适合),而是让用户提供两者的论点相同。当您使用笛卡尔坐标时,设置 x、y、z、w 要简单得多,并且对于径向坐标使用这些相同的名称会很尴尬。而且两者都比数组索引更简单。您可能还有另一个参数,用于给出所提供坐标的类型(笛卡尔坐标或径向坐标)。因此,您将拥有一个受歧视的工会,正如 pdbartlett 所说的那样。
在这种情况下,双层大括号是无用的,因为可以通过数组(双层大括号)或通过内部结构之一来初始化数组。
更正:双层大括号避免将输入强制转换为 GLFloats。
最后一个细节:未命名的内部结构不是标准 C,标准的做法是为内部结构命名,如
In your example, if we consider the name of the variables, the union is most certainly not used to access the same memory cell through say x and r (as a radius and an x coordinate would not fit well), but to leave user provide the same argument for both. It's much simpler to set x, y, z, w when you use cartesian coordinates and would be awkward to use these same names for radial coordinates. And both are simpler than just array indices. You probably also have another parameter around that give the type of the provided coordinate (either cartesian or radial). Thus you will have a discriminated union as pdbartlett calls them.
In this case the double level of braces is useless as the array can be initialized either through the array (double level of braces) or through one of the inner struct.
correction: the double level of braces avoid casting inputs to GLFloats.
Last detail: unnamed inner structs is not standard C, the standard way to do things is to give names to inner structs like in
如前所述,代码使用不同的名称和数据类型分配相同的内存。有时,允许处理命名向量组件 (xyzw) 会很舒服,而在其他时候仍然能够将向量视为数组。
不过,笛卡尔结构和径向结构的名称似乎互换了。 “r”、“theta”和“phi”是径向坐标的常用名称,而不是通常表示为“x”、“y”和“z”的笛卡尔坐标。
我认为值得注意的是,使用不同的表示形式并不严格符合标准(但可能在所有现有的 C 实现上都可以正常工作),原因有两个:
As have been noted, the code allocates the same memory using different names and datatypes. It can some times be comfortable to be allowed to work on named vector-components (xyzw), while still being able to treat the vector as an array at other times.
It looks like the names for the cartesian and the radial structs are swapped, though. "r", "theta" and "phi" are common names for radial coordinates, not cartesian ones which are usually denoted as "x", "y" and "z".
I think it's worth noting that using the different representations is not strictly standard-compliant (but probably works fine on all existing C-implementations), for two reasons: