为什么C语言指针数组支持字符串,却不支持整型/字符数组字面量直接赋值?
底层差异核心原因
核心是C语言中只有字符串字面量是自带内存空间、可直接取地址的匿名数组对象,普通的花括号初始化列表本身不对应任何可寻址的内存对象,具体规则拆解如下:
1. 指针数组的赋值要求
指针数组的每个元素都必须是一个合法的内存地址,指向一个已经分配了存储空间的对象。
你提前定义st、st2数组时,编译器会根据你声明的数组类型,在对应存储区域(全局区/栈区,取决于定义位置)分配好对应的内存空间,数组名st在大多数语境下会自动退化为指向数组首元素的指针,因此可以直接放进int*类型的指针数组,符合语法要求。
2. 直接用花括号列表报错的原因
你写的如下代码中:
int *day_tab[]= { {0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} };
每一组{...}都只是初始化列表,它只是用来给变量初始化的语法结构,本身不是合法的表达式,没有对应的内存地址,也不代表任何数组对象,自然没办法给需要地址值的int*类型元素赋值。
同理char *day_tab[] = {{'0','1','\0'}}中的{'0','1','\0'}也只是初始化列表,不对应任何可寻址的char数组,所以也会报错。
3. 字符串字面量可以正常运行的原因
C标准明确规定:双引号包裹的字符串字面量(比如"01")属于静态存储期的匿名char数组:
- 编译器会在程序编译阶段,把字符串字面量存入只读数据段(.rodata),自动在末尾补
\0,分配固定的内存空间 - 字符串字面量作为表达式使用时,会自动退化为指向这个匿名char数组首元素的
char*指针
因此可以直接把它赋值给char*类型的变量,放进char*指针数组完全符合语法要求。
拓展:无需提前定义具名数组的写法
如果你不想单独声明st、st2这类具名数组,也可以用C99标准引入的复合字面量语法,显式告诉编译器生成匿名数组对象:
int *day_tab[]= { (int[]){0,31,28,31,30,31,30,31,31,30,31,30,31}, (int[]){0,31,29,31,30,31,30,31,31,30,31,30,31} };
这段代码可以正常编译运行,(int[]){...}就是复合字面量,会生成一个可寻址的匿名数组对象,自动退化为指针后就可以赋值给int*类型元素。
内容的提问来源于stack exchange,提问作者Haznut
相关产品推荐
相关产品推荐

