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

C语言中访问部分赋值数组的未赋值区域是否具有良好定义?

访问部分赋值数组的未赋值区域:定义性分析

咱们来把这个问题掰扯清楚,结合C标准的规则和你的例子一步步分析:

先看foo()里的两种情况

void foo() { 
  char s[10]; 
  char v1 = s[0]; // 你的注释标了UB,其实这里需要澄清
  char v2 = s[10]; // 这才是明确的UB
}
  • s[0]:这个数组是自动存储期的局部变量,没初始化,所以元素是不确定值。但因为是char类型,C标准明确规定字符类型不存在陷阱表示,所以读取这个值的行为其实是良定义的——只是你得到的是内存里遗留的随机垃圾值,不是未定义行为。
  • s[10]:这是明确的数组越界访问,直接踩过了数组的内存边界,属于标准里的未定义行为,编译器可以任意处理这段代码,绝对要避免。

重点分析bar()里的s[4]

void bar() { 
  char s[10]; 
  strcpy(s, "foo"); 
  char v3 = s[3]; // v3是'\0',没问题
  char v4 = s[0]; // v4是'f',没问题
  char v5 = s[4]; // 这就是你问的情况
}

strcpy把"foo"(包括末尾的终止符'\0')复制到s里,所以s[0]到s[3]的值是确定的。而s[4]到s[9]这些元素,因为没被初始化或赋值,它们的值是不确定值。

那读取s[4]的行为到底怎么样?答案是:

行为是完全良定义的,但得到的值是不确定的。

理由很简单:

  1. s[4]在数组的合法范围内(数组下标从0到9),没有越界,所以不会触发数组越界的未定义行为。
  2. 还是那句话,char类型没有陷阱表示,读取它的不确定值是标准允许的操作——你会得到一个随机的字节值,可能是之前程序运行遗留的垃圾,每次执行结果可能不一样,但这个读取动作本身是符合C标准的,不属于未定义行为。

最后总结几个关键规则

  • 数组越界访问:不管数组有没有赋值,只要下标超出范围(比如s[10]),绝对是未定义行为,碰都别碰。
  • 访问未赋值的自动存储char元素:行为合法,但值是不确定的垃圾值。
  • 访问未赋值的非char自动存储元素:如果该类型存在陷阱表示(比如某些平台上的有符号int),读取就是未定义行为;否则值不确定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:07:36