为什么不能在 c 中初始化 main() 之外的结构值?

Nat*_*ium 2 c struct structure

我在 Visual Studio 中收到错误代码:

struct coordinates {
    int x;
    int y;
};
struct coordinates point;
point.x = 5;
point.y = 3;

int main() {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我初始化point.xand point.yinmain()和/或如果我给出这样的点值,它就会起作用:struct coordinates point = {5, 3}。为什么不能point.xpoint.y之外初始化main()

Ben*_*tto 6

其他答案(正确地)解释了有一些方法可以通过外部静态命名成员来初始化结构main,但我想为OP或其他人添加。

这里的基本思想是 C 不允许函数之外的可执行语句(“代码”)。新的 C 程序员可能来自另一种语言,其中代码在“全局范围”中频繁执行,并且您可以根据需要到处定义函数或设置变量。C 比这更古老,也更结构化。有全局变量(如您的point),它们是您在任何特定函数之外声明的东西,但您不能真正在全局空间本身中对这些变量“做一些事情”,除非指示它们的初始值(静态初始化)。

C 不会“遍历文件并按顺序执行它找到的所有内容”——每个文件都被编译成一个目标代码单元,然后该目标代码单元与其他单元链接在一起,并且(main本质上)是执行的入口点,而该单元又是执行的入口点调用其他函数,等等——当你的代码运行时,它总是在某个函数的“内部”。

确实,文件中声明和定义的顺序在 C 中很重要,但这本质上是为了编译器的方便,而不是因为在运行时按该顺序“执行”或“求值”。(当您的代码执行时,它已完全转换为其他内容,并且原始文件中的语句顺序基本上已从视图中消失。)

所以!话虽如此:在程序初始化时预先设置全局变量的值是有用的并且通常是可取的。因此,静态初始化有点特殊,因为它看起来可执行语句,但实际上并非如此,因此它传统上具有愚蠢的语法。我们有那种奇怪的有序= {2, 3}语法,现在命名成员有更多的调整来帮助您完成这个静态初始化。但您仍然应该将其视为静态(一次性、固定)初始化,而不是在全局空间中执行赋值,因为这不是您实际正在做的事情。


R..*_*R.. 5

您编写的形式不是初始化;它是一个未初始化的(或者更确切地说默认初始化为零)声明和定义,后跟赋值语句,超出了它们的有效范围。

如果要按名称初始化成员,请编写:

struct coordinates point = {
    .x = 5,
    .y = 3,
};
Run Code Online (Sandbox Code Playgroud)

  • @Natrium - 您可以按照此答案所示的命名方式设置它们一次。不过,您永远不会“更改”它们 - 该语法根本不会以您可能期望的方式“执行” - 它使用了一条指令给编译器,*这个变量*应该具有*这个值*启动。该信息作为特殊条件保留在输出程序中,与编码为可执行语句不同。我在这里写了另一个答案,其中包含有关该概念的更多背景信息。 (3认同)