关于C标准中条件运算符涉及VLA指针的类型判定问题
条件表达式
1 ? 0 : (int(*)[f()]) 0的类型与行为分析 假设存在以下函数:
int f(void) { return 42; }
请问表达式1 ? 0 : (int(*)[f()]) 0的类型是什么?该表达式的值必定等于NULL,但类型无法确定。
int(*)[f()]是指向大小为f()的变长数组(VLA)的指针,但确定该类型需要求值f(),而这个分支属于条件运算符中不会被求值的分支。
根据C17标准6.5.15第4款:
当第一个操作数不等于0时才会求值第二个操作数;当第一个操作数等于0时才会求值第三个操作数
条件运算符的规则要求空指针常量0需与另一分支的类型结合,依据C17标准6.5.15第6款:
……若其中一个操作数是空指针常量,结果类型为另一操作数的类型;……
这就产生了矛盾:确定结果类型需要知晓未求值分支的类型,但该类型依赖于未被调用的函数f()的返回值。可能的解决方案包括:
int(*)[f()]:无论条件判断结果如何,都会求值f()int(*)[]:数组类型保持不完全状态- 未定义行为(UB)
- 其他情况?
C17标准6.2.7第3款的复合类型规则暗示这可能属于未定义行为,但不确定该规则是否适用于此场景。
基于C17/C2X的规范解答
从C17规范的角度来看,该场景属于未定义行为。原因在于:条件运算符的结果类型推导需要明确两个分支的类型,而第三个分支的类型是指向变长数组的指针——变长数组的类型依赖于运行时求值,即使该分支未被执行,C标准并未明确规定类型推导阶段是否需要求值其大小表达式。而复合类型规则中提到,当两个类型需要兼容才能形成复合类型时,若其中一个是依赖运行时的变长数组类型,这种情况下没有明确的兼容规则,因此触发未定义行为。
C2X的草案对变长数组的类型推导规则有所调整,但目前仍未明确这种未求值分支的VLA类型处理逻辑,因此同样倾向于认定为未定义行为。
内容的提问来源于stack exchange,提问作者tstanisl
相关产品推荐
相关产品推荐

