[英]Is this a proper usage of union
I want to have named fields rather than indexed fields, but for some usage I have to iterate on the fields. 我想要命名字段而不是索引字段,但是对于某些用法,我必须在这些字段上进行迭代。 Dumb simplified example: 哑巴简化示例:
struct named_states {float speed; float position;};
#define NSTATES (sizeof(struct named_states)/sizeof(float))
union named_or_indexed_states {
struct named_states named;
float indexed[NSTATES];
}
...
union named_or_indexed_states states,derivatives;
states.named.speed = 0;
states.named.position = 0;
...
derivatives.named.speed = acceleration;
derivatives.named.position= states.named.speed;
...
/* This code is in a generic library (consider nstates=NSTATES) */
for(i=0;i<nstates;i++)
states.indexed[i] += time_step*derivatives.indexed[i];
This avoid a copy from named struct to indexed array and vice-versa, and replace it with a generic solution and is thus easier to maintain (I have very few places to change when I augment the state vector).It also work well with various compiler I tested (several versions of gcc/g++ and MSVC). 这样可以避免从命名结构复制到索引数组,反之亦然,并用通用解决方案替换它,因此更易于维护(当增加状态向量时,我几乎没有地方要更改),并且在各种情况下也能很好地工作我测试过的编译器(gcc / g ++和MSVC的多个版本)。
But theorically, as I understand it, it does not strictly adhere to proper union usage since I wrote named field then read indexed field, and I'm not sure at all we can say that they share same struct fields... 但是从理论上讲,据我了解,它并不严格遵循正确的并集用法,因为我编写了命名字段然后读取了索引字段,而且我不确定我们是否可以说它们共享相同的结构字段...
Can you confirm that's it's theorically bad (non portable)? 您可以确认这在理论上是不好的(非便携式)吗?
Should I better use a cast, a memcpy() or something else? 我是否应该更好地使用演员表,memcpy()或其他东西?
Apart theory, from pragmatic POV is there any REAL portability issue (some incompatible compiler, exotic struct alignment, planned evolutions...)? 从理论上讲,从实用的POV来看,是否存在任何真正的可移植性问题(某些不兼容的编译器,奇异的结构对齐,计划的开发...)?
EDIT: your answers deserve a bit more clarification about my intentions that were: 编辑:关于我的意图,您的答案值得进一步澄清:
I need to know 我需要知道
There's no requirement that the two fields in named_states line up the same way as the array elements. 不需要named_states中的两个字段与数组元素排成一行。 There's a good chance that they do, but you've got a compiler dependency there. 他们很有可能这样做,但是那里有编译器依赖性。
Here's a simple implementation in C++ of what you're trying to do: 这是您要尝试执行的C ++中的简单实现:
struct named_or_indexed_states {
named_or_indexed_states() : speed(indexed[0], position(indexed[1]) { }
float &speed;
float &position;
float indexed[2];
};
If the size increase because of the reference elements is too much, use accessors: 如果由于引用元素导致大小增加太多,请使用访问器:
struct named_or_indexed_states {
float indexed[2];
float& speed() { return indexed[0]; }
float& position() { return indexed[1]; }
};
The compiler will have no problem inlining the accessors, so reading or writing speed()
and position()
will be just as fast as if they were member data. 编译器将内联访问器毫无问题,因此读取或写入speed()
和position()
速度将与它们是成员数据一样快。 You still have to write those annoying parentheses, though. 但是,您仍然必须写那些令人讨厌的括号。
Only accessing last written member of union is well-defined; 只有访问工会的最后书面成员才能明确定义; the code you presented uses, as far as only standard C (or C++) is concerned, undefined behavior - it may work, but it's wrong way to do it. 就仅涉及标准C(或C ++)而言,您提供的代码使用的是不确定的行为 -可能起作用,但这是错误的方式。 It doesn't really matter that struct uses the same type as the type of array - there may be padding involved, as well as other invisible tricks used by compiler. struct使用与数组类型相同的类型并不重要-可能涉及填充,以及编译器使用的其他隐形技巧。
Some compilers, like GCC, do define it as allowed way to achieve type-punning. 一些编译器,例如GCC,确实将其定义为实现类型绑定的允许方式。 Now the question arises - are we talking about standard C (or C++), or GNU or any other extensions? 现在出现了问题-我们是在谈论标准C(或C ++),GNU还是任何其他扩展?
As for what you should use - proper conversion operators and/or constructors. 至于您应该使用什么-适当的转换运算符和/或构造函数。
This may be a little old-fashioned, but what I would do in this situation is: 这可能有点过时,但是在这种情况下,我要做的是:
enum { 枚举{
F_POSITION, F_POSITION,
F_SPEED, F_SPEED,
F_COUNT }; F_COUNT};
float states[F_COUNT]; 浮动状态[F_COUNT];
Then you can reference them as: states[F_POSITION] and states[F_SPEED]. 然后,您可以将它们引用为:状态[F_POSITION]和状态[F_SPEED]。
That's one way that I might write this. 那是我可能写这个的一种方式。 I'm sure that there are many other possibilities. 我确信还有很多其他可能性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.