在C语言中,Double的结构可以被类型转换为Double的数组吗?

在C语言中,Double的结构可以被类型转换为Double的数组吗?,c,struct,casting,C,Struct,Casting,这在C语言中合法吗 struct Doubles { double a,b,c; }; void foo(struct Doubles* bar) { double* baz = (double*)bar; baz[0]++; baz[1]++; baz[2]++; } 我知道它在MSVC 2010上“有效”,但我不知道它是否合法,或者不同的布局是否会导致UB。编译器可以随意填充/打包结构,所以严格来说,您的代码不是100%安全的。不过,它可以在大多数实现中使用。这会导致

这在C语言中合法吗

struct Doubles
{
  double a,b,c;
};

void foo(struct Doubles* bar)
{
  double* baz = (double*)bar;
  baz[0]++;
  baz[1]++;
  baz[2]++;
}


我知道它在MSVC 2010上“有效”,但我不知道它是否合法,或者不同的布局是否会导致UB。

编译器可以随意填充/打包结构,所以严格来说,您的代码不是100%安全的。不过,它可以在大多数实现中使用。

这会导致未定义的行为。该标准并未完全规定结构的布局。例如,可能会有填充。

虽然大多数编译器都可以使用它,但我要问的问题是,如何比使用
bar->a
bar->b
、和
bar->c
?@RSahu更好,因为我希望在循环中迭代结构的成员,因为我需要对每个成员执行完全相同的操作。我可以将操作包装在一个函数中,然后使用指向三个成员的指针调用该函数(这可能是我将要做的,因为答案似乎是“不,这不是完全安全的”),但这不太方便。@anjruu如果要迭代,请使用数组。@self我正在使用现有的库。所讨论的结构表示一个点,而代码的原始作者选择将一个点表示为具有x、y和z位置成员的结构。@anjruu除非您希望具有未定义的行为,否则您必须调用这些成员。
struct
的内存布局描述得非常严格,即。E保证使用要求的订单。结构中的填充与数组中的填充相同。这有一些限制:只有在成员之后,具有相同初始序列的任何结构都必须具有相同的偏移量。@cmaster结构中的填充与数组中的填充相同吗?真正地标准中规定的在哪里?@DavidHeffernan您需要填充什么?您需要它将下一个成员与允许CPU快速访问的边界对齐。差不多没什么。CPU并不关心它是从结构还是数组加载,见鬼,它甚至不知道。因此,任何健全的编译器在这两种情况下都必须使用相同的填充。@cmaster我们讨论的是标准,而不是任何具体的实现。我认为您解释得很好。为了提高效率并轻松满足“兼容类型”和“联合”要求,可以添加这一点,在几乎每个实现中的每个成员之后,仅添加最小必要的填充量以满足对齐约束。因此,在实践中,以两个
T
开头的结构的初始部分将与两个
T
的数组兼容;这不是导致未定义行为的问题。相反,此处未定义的行为是由别名引起的。
struct double
类型的对象不能为
double[3]
类型的对象加别名,编译器可以假定它们不加别名,这意味着读写可以通过中断代码的方式自由重新排序。@R。。严格的别名规则适用于基本类型,这两种情况下都是
double
。所以,不,别名不会呈现此代码。还有数组边界规则<代码>双*baz=(双*)条;baz[0]++是合法的,
baz+1
作为超过“长度1数组”
条末端的指针是合法的。a
baz[1]++
是UB(解除对ST指针的引用),而
baz[2]
在解除引用之前只是调用非法指针算术(UB)。所以这里有很多问题。