【问题标题】:why can't you initialize values of structs outside of main() in c?为什么不能在 c 中初始化 main() 之外的结构值?
【发布时间】:2020-11-17 09:11:04
【问题描述】:

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

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

int main() {
    return 0;
}

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

【问题讨论】:

  • 你为什么要这样做?
  • @EdHeal 我不想那样做。我只是好奇为什么我是这样的。

标签: c struct structure


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

    也许您学过 Javascript,但您是 c/c++ 的新手。 每个c/c++程序都以main函数开头,每个执行代码都必须在一个函数中。

    所以如果你想初始化一个结构的值,你应该在主函数中这样做。

    struct coordinates {
        int x;
        int y;
    };
    struct coordinate point;
    int main(){
      point.x = 5;
      point.y = 3;
    }
    

    【讨论】:

    • C 确实允许静态初始化,因此您不需要需要在main 中初始化静态结构。不要忘记main 也不一定是程序中运行的第一个代码。
    • 另外...你在main()中所做的不是初始化而是赋值。
    【解决方案3】:

    为什么不能在 main() 之外初始化 point.x 和 point.y?

    您可以,using static initialization - 但您不能调用函数或执行不纯操作。在 C99 之前使用静态初始化时,您需要确保以正确的顺序设置字段,而 C99 及更高版本允许 designated initializers 允许任意字段初始化。

    函数外的 C 代码不是可执行指令 - 它们是静态声明,因此它们没有定义的评估顺序。

    作为一个思想实验,考虑一下:

    int x;
    int y;
    
    x = 2;
    y = 3;
    y = x;
    x = y;
    
    int main() {
        
        return x; // what is returned?
    }
    

    【讨论】:

    • C90 没有指定的初始化程序。它具有依赖于成员顺序的遗留结构初始化。
    • @R..GitHubSTOPHELPINGICE 哎呀!谢谢 - 我已经更正了我的答案。
    【解决方案4】:

    你写的表格不是初始化;它是一个未初始化(或者更确切地说是默认初始化为零)的声明和定义,后跟它们有效范围之外的赋值语句。

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

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

    【讨论】:

    • 我开始看到一种模式:如果我在main 之外定义变量a,然后更改它的值(仍然在main 之外),我会得到一个错误。所以由于point.xpoint.y默认设置为0,我不能更改它们,对吗?
    • @Natrium - 您可以按此答案所示的命名方式设置它们一次。但是,您永远不会“更改”它们-此语法根本没有以您可能期望的方式“执行”-它使用了此变量应该具有的编译器指令此值 在启动时。该信息作为特殊条件保存在输出程序中,与被编码为可执行语句不同。我在这里写了另一个答案,关于这个概念有更多的背景。
    猜你喜欢
    • 2017-05-17
    • 2016-02-22
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2023-04-01
    • 2020-01-05
    • 2011-01-19
    • 1970-01-01
    相关资源
    最近更新 更多