我想要命名字段而不是索引字段,但是对于某些用法,我必须迭代字段。愚蠢的简化例子:
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];
这避免了从命名结构到索引数组的复制,反之亦然,并用通用解决方案替换它,因此更容易维护(当我增加状态向量时,我几乎没有什么地方可以改变)。它也有效以及我测试的各种编译器(gcc / g ++和MSVC的几个版本)。
但理论上,正如我所理解的那样,它并没有严格遵守正确的联合使用,因为我编写了命名字段然后读取了索引字段,我不确定我们可以说它们共享相同的结构字段......
你能否证实这是理论上不好的(非便携式)?
我应该更好地使用演员表,memcpy()还是别的什么?
除了理论之外,从实用的POV是否有任何真正的可移植性问题(一些不兼容的编译器,奇异的结构对齐,计划的演变......)?
编辑:您的答案应该更加明确我的意图:
我需要知道
答案 0 :(得分:3)
并不要求named_states中的两个字段与数组元素的排列方式相同。他们很有可能,但你在那里有编译器依赖。
这是C ++中您正在尝试做的一个简单实现:
struct named_or_indexed_states {
named_or_indexed_states() : speed(indexed[0], position(indexed[1]) { }
float &speed;
float &position;
float indexed[2];
};
如果由于引用元素而导致的大小增加太多,请使用访问器:
struct named_or_indexed_states {
float indexed[2];
float& speed() { return indexed[0]; }
float& position() { return indexed[1]; }
};
编译器在内联访问器时没有问题,因此读取或写入speed()
和position()
的速度与成员数据一样快。不过,你仍然需要编写令人讨厌的括号。
答案 1 :(得分:2)
只有访问最后一个联合书面成员才能明确定义;您提供的代码使用,就标准C(或C ++)而言,未定义的行为 - 它可能有效,但这是错误的方法。结构使用与数组类型相同的类型并不重要 - 可能涉及填充,以及编译器使用的其他不可见技巧。
一些编译器,如GCC,确实将其定义为实现类型惩罚的允许方式。现在问题出现了 - 我们是在谈论标准C(或C ++),还是GNU或任何其他扩展?
至于你应该使用什么 - 适当的转换运算符和/或构造函数。
答案 2 :(得分:1)
这可能有点过时,但在这种情况下我会做的是:
枚举 {
F_POSITION,
F_SPEED,
F_COUNT };
浮动状态[F_COUNT];
然后您可以将它们引用为: 状态[F_POSITION]和状态[F_SPEED]。
这是我写这篇文章的一种方式。我确信还有很多其他可能性。