C语言全局区结构体:为何可初始化却不能直接赋值?
全局作用域下结构体初始化与赋值的区别
相关代码文件
Define.c
#include "Define.h" // this line working // Format date_format = { "YYMMDD", "%02u%02u%02u", 6, 3 }; // line1 Format date_format; // this line are now working strcpy(date_format.format, "YYMMDD"); // line2 strcpy(date_format.scanformat, "%02u%02u%02u"); // line3 date_format.scansize = 3; // line4 date_format.printsize = 6; // line5
Define.h
#ifndef _DEFINE_H #define _DEFINE_H typedef struct Format { char format[256]; char scanformat[256]; unsigned int printsize; unsigned int scansize; } Format; extern Format date_format; #endif
main.c
#include <stdio.h> #include "Define.h" int main(int argc, char* argv[]) { printf(date_format.format); getchar(); return 0; }
疑问
使用Visual Studio 2017开发时,为何在Define.c的全局作用域中,line1的结构体初始化语句可以正常工作,但line2-5的直接赋值语句却无法运行?是否此类赋值语句必须放在函数内部?
解答
这是C语言的语法规则决定的,核心区别在于全局变量的初始化和运行时赋值是完全不同的两个阶段:
- 全局变量的初始化是在程序启动前的编译链接阶段完成的,C标准只允许用常量表达式或者聚合初始化(比如line1的大括号初始化方式)来完成全局变量的初始赋值,这种操作属于变量定义的一部分,合法合规。
- 而像
strcpy调用、=直接赋值这类操作属于运行时执行语句,这类代码必须放在函数内部(局部作用域),因为全局作用域里只能放置变量/函数的声明、定义以及初始化语句,不能放置需要在程序运行时执行的逻辑代码。
具体到你的代码:
- line1是结构体的聚合初始化,属于全局变量定义时的初始化操作,符合C语言的语法要求,所以能正常编译运行。
- line2到line5都是需要在程序运行时执行的语句,把它们放在全局作用域里会触发编译器报错,因为这违反了C语言对全局作用域代码的限制。
如果想完成类似line2-line5的赋值操作,有两种可行方案:
- 直接使用line1的聚合初始化方式完成全局变量的定义和赋值。
- 编写一个初始化函数,把line2-line5的代码放到函数内部,然后在
main函数的开头调用这个初始化函数。
内容的提问来源于stack exchange,提问作者nascent
相关产品推荐
相关产品推荐

