为什么结构体不能直接赋值?

32

假设我有一个已经定义好的标记为MyStruct的结构体,假设x, y,...,z是它的字段允许的值。那么为什么会是这样的:

struct MyStruct q = {x,y,..,z};

允许,但是

struct MyStruct q;
q = {x,y,...,z};

这是不被允许的吗?我发现这非常令人烦恼。在第二种情况下,我之前声明了q,我需要逐个为每个字段分配一个值:

q.X = x; q.Y = y; ... q.Z = z;

其中X,Y,...,ZMyStruct的字段。这背后有什么原因吗?


赋值的rvalue在运行时并不确定,但初始赋值是确定的,并且可以在二进制文件中访问(如果是ELF文件,则最可能在.BSS部分)。如果您想将结构体相互赋值,可以将q赋值为某些初始化的内容。例如: struct MyStruct w = {x,y,..,z}; q = w - sardok
2个回答

48

你正在寻找的是复合字面量。这是在C99中添加到语言中的。

您的第一个情况:

struct MyStruct q = {x,y,..,z};

在初始化语法中,这是一种特定的语法。根据语言的严格定义,你的第二个情况不属于初始化,而是赋值。赋值语句右边的结构必须是正确类型的结构。在 C99 之前,语言中没有语法可以编写 struct 字面量(即你正在尝试做的)。{x,y,..,z} 看起来像一个带有表达式的块。如果有人试图将其视为字面量值,虽然语言并没有这样做,但他们不能确定它的类型。(在你的上下文中,你可能会猜测得很好。)

为了允许这个并解决类型问题,C99 添加了语法,使你可以写成:

q = (struct MyStruct){x,y,...,z};

5
+1 是指明它是 C99 标准。我不知道这是可能的,可能是因为我们必须使用旧编译器。 - Leo

27
你可以这样做,但在聚合操作之前需要提供结构的类型:
struct MyStruct q;
q = (struct MyStruct){x,y,...,z};

2
但仅限于C99(参见Avi Berger的答案) - AAT
1
@AAT 您说得对,这是 C99 中新增的一个特性。然而,由于 C99 已经存在了十多年,在许多情况下,它已经成为 C 的代名词。 - Sergey Kalinichenko
@AAT 它不起作用。我正在使用Visual Studio 2010,Windows。我遇到了语法错误,它无法编译。我期望Visual Studio支持最新的标准。我一定是错过了某个设置或者其他什么东西。有什么想法吗?也许我应该针对这个问题开一个新的问题? - a06e
4
你的期望值太高了... 微软工具很少使用最新的标准。 - Karoly Horvath
该死...你说得对。我刚找到了这个链接:https://dev59.com/enVC5IYBdhLWcg3w51vy。在 Google 一番之后,似乎微软没有支持 C99 或 C11 的计划。 - a06e

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接