C 结构成员赋值不在函数内时导致语法错误

C 结构成员赋值不在函数内时导致语法错误,c,C,我想在C编程语言中为(用户定义的)全局变量指定一个特定值。当我在任何其他函数或主函数中执行此操作时,它是好的。但是,当我从全局空间(在任何函数之外)执行此操作时,会出现以下编译错误: [expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token] 以下是导致问题的代码段: #include <stdio.h> #define MAX_SIZE 5 typedef struct { int val[MA

我想在C编程语言中为(用户定义的)全局变量指定一个特定值。当我在任何其他函数或主函数中执行此操作时,它是好的。但是,当我从全局空间(在任何函数之外)执行此操作时,会出现以下编译错误:

[expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token]
以下是导致问题的代码段:

#include <stdio.h>
#define MAX_SIZE 5

typedef struct
{
    int val[MAX_SIZE];
    int top;
}stack_t;

stack_t s;
s.top = -1;  // <== Initialization from here is causing compilation error

main()
{
    //s.top = -1; < === Initialization from here is fine  
    printf("s.top =%d\n", s.top);
    return 0;
}
#包括
#定义最大尺寸5
类型定义结构
{
int val[最大值];
int top;
}堆叠;
堆栈;

s、 top=-1;// 在
main
外部初始化是该错误的原因。你可以像这样使用它

stack_t s={.top=-1};

它将允许您在声明时进行初始化。请参考此内容,否则可能会很有用

C代码必须位于函数内部。可以在函数外部声明全局,但不能在函数外部编写赋值语句。也就是说,您可以将初始值设置为声明结构的一部分,但随后不能更改它。这里您的声明只是“堆栈”行

C中的所有内容最终都编译成二进制格式的符号(例如ELF格式)。符号有名称,因此函数被命名为代码块,全局函数被命名为数据块。编译后的二进制文件中没有“自由浮动”块,所有内容都必须使用一个名称

在C模型中,在函数外部浮动的代码没有意义,因为C没有运行该代码的位置。C永远不会像bash、Python或javascript那样运行文件;它只运行二进制文件。所以它只运行名为
功能。只有在编译时而不是运行时才知道这些文件。

在全局空间中,您只能初始化和声明变量,但不能将值分配给变量。在您的代码中,您正在将值分配给struct的成员,因此它的抛出错误对于下面代码中的整数也是如此

在全局空间中尝试以下代码,效果良好:

typedef struct 
{
     int val[MAX_SIZE];
     int top;
}stack_t;

stack_t s={{},-1};

main()
{
    printf("s.top=%d",s.top);
    return 0;
}

s.top
的赋值错误并不奇怪。它不是一个初始化,而是一个赋值,这些在C语言中是不同的概念。在函数之外不能有赋值

这里有趣的是,看起来您可以对整型变量k进行赋值。但这是一种错觉,因为在这种情况下,它不是一个赋值,而是一个初始化

线路

k = 10;
不是解释为赋值,而是解释为变量定义。这方面的一个提示是,GCC给出了警告“数据定义没有类型或存储类”和“在'k'的声明中,类型默认为'int'。所以这行可以写成

int k = 10;
正如Matt在下面的评论中所写的那样,省略这样的数据类型似乎是一个GCC扩展,而不是标准所允许的

(顺便说一下,一定要在编译器中打开警告,并注意它们!)

但是等等,上面这行不是已经有了k的定义吗?你不能有多个定义,对吗

首先,请记住C对定义和声明进行了区分。变量的定义是当您“创建”变量时,并且可以选择为其提供初始值。声明就是告诉编译器变量存在、名称和数据类型,但定义在别处。同一变量可以有一个定义和一个或多个声明。例如:

int xxx = 10; // This is the definition of xxx
int xxx; // This is a declaration of xxx
int xxx; // Another delaration of xxx
int yyy;
但有时编译器无法确定它看到的是一个声明还是一个定义,然后将其解释为“暂定定义”,或者换句话说,“可能是一个定义,可能只是一个声明,我们稍后再决定”。例如:

int xxx = 10; // This is the definition of xxx
int xxx; // This is a declaration of xxx
int xxx; // Another delaration of xxx
int yyy;
这是变量yyy的定义(没有初始值),还是仅仅是一个声明,定义将在别处找到?编译器不知道,所以等待决定,并将其称为暂定定义

当编译器看到您对k的第一个声明(以及其他变量i、j和l)时,它将被解释为一个暂定定义,当找到后一个定义时,k的暂定定义将被确定为一个声明,而不是定义。

有。您应该注意,赋值不能在函数之外完成。声明

s.top = -1;  
是一个赋值而不是一个初始化

C99和后者提供了一系列结构和数组。因此,您只能将struct
s
top
成员初始化为

stack_t s = { .top = -1 };   

其他成员将由编译器初始化为
0

:感谢您的回复,我知道我们可以在声明为可能时初始化。但对于整数变量,编译器不会抛出error@sudhi一个正态变量,你可以这样做
inta;a=10
它将发出警告
数据定义没有类型或存储类[默认情况下启用]
。我也很好奇为什么在main()之外初始化会导致编译错误。
{}
在CI中不是有效的初始值设定项,请相信它的
{0}
。但是使用
{}
编译器并没有抛出错误。让我知道你的评论-@Matt McNabbYou依赖于编译器扩展,如果
{}
没有给出错误这些行:stack\t s;s、 top=-1;不是初始化。初始化将是:stack_t s={“”-1};实际的可执行代码,例如第二行(s.top=-1;)是可执行赋值,而不是初始化定义为GCC扩展;标准C中不允许这样做。请参见6.7.2/2“每个声明中的声明说明符中至少应给出一个类型说明符”。我认为这在C89中是合法的,在C99和C11中肯定不合法however@ThomasPadron-麦卡锡:谢谢你清晰的解释