You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中用初始化列表给int指针赋值为何触发信号11错误

两种写法的核心差异与段错误原因

先纠正一个常见认知偏差

{1,2,3,4} 从来都不是数组,它只是C语言语法里定义的初始化列表,属于纯语法层面的构造,没有自己独立的内存空间,也没有固定类型,只有和具体要初始化的目标类型绑定的时候,才会产生对应的初始化逻辑,脱离目标类型谈初始化列表没有任何意义。

报错写法的实际执行逻辑

你写的 int *p = {1,2,3,4}; 里,指针p是标量类型(也就是单值类型,和数组、结构体这类可以存多个值的聚合类型对应)。C标准明确规定:用初始化列表给标量类型初始化时,只会取列表里的第一个值给变量赋值,列表里剩下的多余值会被直接丢弃,只要开了基础编译警告,这行代码就会报“初始值元素过多”的警告,很多人忽略警告直接跑就会踩坑。
说白了这行代码编译完实际等价于:

int *p = (int*)1;

这时候指针p里存的地址就是整数1,指向内存低地址段的操作系统保护区,用户态程序对这个地址没有任何访问权限。后面执行*p做解引用的时候,直接访问非法内存,自然就触发信号11(段错误)把程序杀了。

先定义数组再给指针赋值为什么正常

当你先写int arr[] = {1,2,3,4};的时候,初始化列表的初始化目标是int[]数组(聚合类型),编译器会根据列表里的元素个数,在栈上开一块连续的4*sizeof(int)大小的内存,依次把1、2、3、4存到对应位置,这时候才真正生成了一个实打实的数组。
这时候再写int *p = arr;,会触发C语言里非常常见的数组隐式退化规则:数组类型的表达式作为右值使用时,会自动转换成指向数组第一个元素的指针。这时候p里存的是栈上合法内存的地址,解引用访问的是你自己申请的栈空间,当然不会报错,此时*p + 1取到首元素1再加1,最终输出2。

补充:想直接用列表给指针赋值的正确写法

如果不想单独定义数组,C99及之后的标准支持复合字面量语法,只要显式指定列表对应的类型即可:

int *p = (int[]){1,2,3,4};

这行代码会生成一个匿名的int数组,再把数组首元素的地址赋值给p,效果和先定义数组再赋值完全一致,可以正常运行。你之前的写法就是少了(int[])这个类型指定,编译器根本不会把后面的初始化列表识别成数组。


内容的提问来源于stack exchange,提问作者John Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:27:25