我可以将结构视为数组吗?

spe*_*wah 7 c pointers vector

我有一个用于保存4D向量的结构

struct {
    float x;
    float y;
    float z;
    float w;
} vector4f
Run Code Online (Sandbox Code Playgroud)

我正在使用一个库,它有一些函数可以在向量上运行,但是以浮点指针作为参数.

打电话是否合法doSomethingWithVectors( (float *) &myVector)

Jam*_*olk 10

它可能有效,但它不可移植,编译器可以自由地对齐事物,以便一个浮点数不会立即跟随另一个浮点数.

  • @John Knoeller:不正确.首先,C语言没有对数组和结构都相同的"打包规则".实际上,规则明显不同:结构可以添加填充,数组不能.其次,这个代码将被打破,原因不仅仅是潜在的包装差异.例如,严格的混叠违规是比打包更重要的问题. (15认同)
  • 对于那些(像我一样)不知道C中的"严格别名"的人来说,实际上有一个问题可以很好地解释它:http://stackoverflow.com/questions/98650/what-is-the-strict-别名规则 (3认同)
  • John:所有编译器都必须遵循`&a [n] + 1 ==&a [n + 1]`的语言规则.结构成员没有这样的规则.如果你想使用特定于编译器的#pragmas或类似的来控制struct layout,那很好; 但我在上面提到的代码中没有看到这一点.最后,编译器特定显然*不可移植. (3认同)
  • -1它会工作,并且它是便携式的.结构包装和阵列包装遵循相同的规则. (2认同)
  • @Aidan,数组之间不能有成员填充.如果我有`T a [N];`,那么`a`和`a + 1`就是`sizeof(T)`bytes. (2认同)

AnT*_*AnT 8

您可以编写将尝试将其视为数组的代码,但该语言不保证该代码的功能.行为未定义.

在C语言中,将一个类型的值占用的存储区域重新解释为另一种类型几乎总是非法的.该规则有一些例外(这就是为什么我说"几乎"),就像你可以将任何对象重新解释为char数组一样,但一般来说它显然是非法的.

此外,可能的危险并不仅仅是理论上的,而且不仅仅是阵列和结构之间可能的对齐差异.现代编译器可能(并且确实)依赖上述语言规则来执行别名优化(例如,在GCC中读取严格别名语义).简而言之,允许编译器在假设一个内存占用的struct内存永远不会重叠由数组占用的内存的情况下翻译代码float.当人们开始使用帖子中的技巧时,这通常会导致意外结果.


Alo*_*hal 6

哇.有很多答案说它会起作用.C标准不保证.在回应评论要求一个真实世界的例子,就是有优良的岗位克里斯托雷克comp.lang.c.最后的引用是:这里的教训与以往一样:"如果你对编译器说谎,它就会报复."

绝对必须阅读那些认为将struct同构成员视为数组的人.

  • 约翰,并不是编译器编写者在那里报复.但是,如果你有不合理的期望,事情会*出错.做他想做的事情有更清洁,更安全的方式. (3认同)