【问题标题】:Why can't you define struct members globally?为什么不能全局定义结构成员?
【发布时间】:2019-06-16 10:24:44
【问题描述】:

当您在全局范围内定义 struct 时,为什么不能在全局范围内定义结构成员(除了使用初始化语法之外)?我从 clang 得到的错误是 system_1 有一个“未知类型名称”。

如果您在函数中定义结构,例如main(),那么您不会遇到任何问题。

typedef struct Light_System {
    int redLightPin;
    int yellowLightPin;
    int blueLightPin;
} Light_System;

Light_System system_1;

# "Light_System system_1 = {4, 0, 0}" works

system_1.redLightPin = 4; # doesn't work

int main(int argc, char *argv[]) {
    # placing everything in here works
    # placing just "system_1.redLightPin = 4;" here makes it work.
    printf("%d\n", system_1.redLightPin);
    return 0;
}

我希望我能够在全局范围内定义结构的成员。

【问题讨论】:

  • 试试这个。在全局范围内初始化变量 x。 int x = 5; 然后在全局范围内重新分配其值 x = 10; 并且它不会编译。您不能在函数之外分配值。不过,您可以初始化值。
  • 我试过了,它确实编译和工作了吗?编辑:我打错了,我明白你的意思。这是为什么呢?
  • 是的。它不应该编译。编辑:我在回答中做了一个小解释。

标签: c struct


【解决方案1】:

当你全局定义结构时,为什么不能全局定义结构成员(除了使用初始化语法之外)?

因为您要做的不是定义初始化。这是一个任务。您可以在全局范围内声明、定义和初始化,但不能赋值。

这不仅适用于结构。它也适用于变量。在函数之外,您只能声明和初始化变量。你不能做常规作业,或者其他任何事情。我不能 100% 确定细节,但我相当有信心您无法在全局范围内做任何在编译期间无法完成的事情。

这样就可以了:

int x=5;

但不是这个:

int x;
x = 5;

嗯,实际上它是有效的,但会产生关于warning: data definition has no type or storage classwarning: type defaults to ‘int’ in declaration of ‘x’ 的神秘警告。然而,仅仅因为它编译,它不会做你认为它会做的事情。实际上,你不理解的神秘警告通常是一个很好的指标,表明代码会做一些你既不想也不理解的事情。这段代码所做的是对x隐式重新声明,然后是初始化。如果之前没有初始化是允许的,所以这是无效的:

int x = 3;
x = 5; // Not ok, because x is already initialized

这里的错误信息清楚地说明了为什么编译前面的示例:error: redefinition of ‘x’

同样,这也是无效的:

int x = foo();  

它给出了这个错误:

main.c:3:7: error: initializer element is not constant
 int x = foo();
         ^~~

【讨论】:

    【解决方案2】:

    正如其他人所说。您不能在全局范围内分配。但是你可以初始化。所以如果要全局初始化struct成员,可以这样尝试。

    #include <stdio.h>
    
    typedef struct Light_System {
        int redLightPin;
        int yellowLightPin;
        int blueLightPin;
    } Light_System;
    Light_System ls = {10,5,3};
    
    int main()
    
    {
        printf("%d %d %d",ls.redLightPin,ls.yellowLightPin,ls.blueLightPin);
    }
    
    

    应该可以编译。

    因此,如果您想知道为什么会发生这种情况,那是因为全局变量存储在应用程序的 .data 部分中,并在编译时具有给定值。但是赋值是只能在函数范围内执行的指令。所以被编译的东西会保留它们的编译时间值。

    【讨论】:

    • 这应该是公认的答案
    【解决方案3】:

    您不能在 C 或 C++ 中的函数之外执行语句。但是你可以在很多编译器(不是全部)中使用 C99 风格的“指定初始化器”:

    Light_System system_1 = {
        .redLightPin = 4
    };
    

    这将成为 C++20 中的标准,但由于相同的语法在 C 中已存在多年,许多编译器也允许在 C++ 中使用它。

    参考:https://en.cppreference.com/w/cpp/language/aggregate_initialization

    【讨论】:

      猜你喜欢
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 1970-01-01
      • 2020-04-02
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多