C语言数组中结构体的初始化行为疑问
为什么结构体数组元素直接用
{...}赋值会报错? 这个问题的核心是C语言中初始化(Initialization)和赋值(Assignment)的区别,以及复合字面量的用法限制,咱们一步步拆解清楚:
1. 先搞懂初始化和赋值的本质区别
初始化是在变量第一次被声明的时候给它设置初始值,这时候C语言允许用
{...}这种初始化列表语法,比如你代码里的:struct Student s = {.name = "Joe", .grade = 10}; // 合法:声明s时初始化 struct Student some_other_students[] = { {.name = "John", .grade = 10} }; // 合法:声明数组时初始化元素这时候
{...}是专门的初始化语法,编译器能正确识别。赋值是给已经存在的变量(已经完成声明、分配好内存的变量)重新设置值,这时候等号右边必须是一个合法的表达式——而单纯的
{...}并不是一个表达式,这就是你报错的根源。
2. 为什么students[0] = {.name = "John", .grade = 10};报错?
students[10]是一个已经声明的结构体数组,students[0]是数组里的第一个元素,它已经是一个存在的结构体变量了。这时候你用=后面直接跟{...},编译器会认为这里需要一个能求值的表达式,但{...}不符合表达式的语法规则,所以就抛出了error: expected expression before '{' token的错误。
3. 那为什么其他几种写法合法?
students[1] = s;:s是一个已经初始化好的结构体变量,C语言允许同类型的结构体变量直接整体赋值——本质上是把s的每个成员的值都拷贝到students[1]对应的成员里,这是合法的赋值操作。students[2].grade = 8;和strcpy(students[2].name, "Billy");:这两个是直接操作结构体的单个成员,students[2].grade是int类型,直接赋值int值没问题;students[2].name是字符数组,用strcpy复制字符串也是对成员的合法操作,和整体赋值的场景完全不同。
4. 怎么让students[0]的赋值合法?
用C99标准引入的复合字面量(Compound Literals),把初始化列表包装成一个临时的结构体表达式就行,语法是(结构体类型){初始化列表}:
students[0] = (struct Student){.name = "John", .grade = 10}; // 现在合法了
复合字面量相当于生成了一个匿名的临时结构体变量,它是一个合法的表达式,可以直接用来赋值或者作为函数参数传递。
内容的提问来源于stack exchange,提问作者venge
相关产品推荐
相关产品推荐

