通过强制转换为结构来分配数组

时间:2016-06-22 15:48:36

标签: c

为什么以下代码有效?

#include <stdio.h>
#define LEN 12

typedef struct
{
    char buffer[LEN];
} string;

int main()
{
    char buffer1[LEN] = "Hello World";
    char buffer2[LEN];

    *(string*)buffer2 = *(string*)buffer1;

    printf("%s",buffer2);
    return 0;
}

据我了解,我不能将一个数组分配给另一个数组。

3 个答案:

答案 0 :(得分:4)

C允许将一个结构分配给相同类型的另一个结构,并且这样做的语义是根据结构表示来定义的,而不是逐个成员的副本。结构表示包含数组的表示并不意味着将包含数组的结构的值赋给另一个结构违反了C禁止将一个数组分配给另一个数组。

此外,C还保证结构的第一个成员的地址与结构本身的地址相同,并且它允许在不同的指针类型之间转换对象指针。在这种情况下,不保证这种转换的结果是正确对齐的,如果不是,那么取消引用该结果会产生未定义的行为。

另一方面,编译器可以在结构表示中包含尾随填充。通常这样做是为了对齐目的。如果你的编译器为你的结构做了那件事 - 如果它对它应用64位或更高的对齐要求它可能会 那么 - 那么你的赋值会产生未定义的行为。在那种情况下,如果它似乎有用,那是因为你很幸运。

但是,如果事实证明上述两种未定义行为都不适用,那么期望代码按预期工作确实是合理的。但是,由于预测是否会出现这种情况很棘手,因此建议您避免使用此类代码。

更好的问题可能是C禁止数组复制的原因。可能有几个原因,但我认为最深的原因只是为了保持一致性。在几乎所有上下文中,当表达式或子表达式求值为数组时,该值衰减到指向第一个数组元素的指针。这包括构成=运算符的操作数的子表达式。因此,在普通的C表达式中,数组赋值实际上是指针赋值,而且没有预期的语义。人们不得不为这种情况仔细制定适当的特殊情况,以便进行阵列分配。

答案 1 :(得分:0)

正如评论中指出的那样,你没有将数组分配给另一个,但是你通过强制转换将结构分配给另一个。 在复制所有元素时分配struct结果(在简单结构的情况下,请参阅此post)。但是代码非常糟糕,您可以通过简单地在结构中添加另一个字段来打破它。

答案 2 :(得分:0)

从您的评论“据我了解,我不能将一个数组分配给另一个。”您似乎创建了结构来绕过无法通过将缓冲区转换为赋值的结构将一个字符串复制到另一个字符串。

这次碰巧工作了,但它不会总是工作;结构通常在字段之间有填充和对齐位。

如果要在C中将一个字符串复制到另一个字符串,请使用strcpystrncpy函数(如果是wchar_t类型字符串,则使用wcscpywcsncpy)。

如果要将任意类型的一个数组复制到另一个数组,请使用for循环逐个复制每个索引,或memcpy函数。