带外部链接无定义标识符用于_Generic是否违语义?兼析C2x 6.9p5
C2x标准6.9p5条款相关问题解答
依据最新的C2x标准(6.9p5),条款原文如下:
外部定义是指同时作为函数(内联定义除外)或对象定义的外部声明。如果带外部链接的标识符被用于表达式中(除作为typeof运算符的操作数且结果为非可变修改类型,或作为sizeof/alignof运算符的操作数且结果为整数常量表达式的情况外),整个程序中必须恰好存在该标识符的一个外部定义;否则,外部定义不得超过一个。
你给出的测试程序:
extern int x; int i = _Generic(x, default: 0); int main(void) { }
核心疑问解答
你的初始理解不正确,程序中不需要为x提供外部定义,编译器不报错是符合标准逻辑的。
原因在于_Generic的控制表达式是不求值的——它仅用于判断操作数的类型,不会触发对x的实际引用或求值行为。而6.9p5条款中要求“必须恰好一个外部定义”的前提,是标识符被用于需要求值的表达式中(条款列的typeof、sizeof/alignof例外,本质也是因为这些操作不需要实际引用标识符定义)。_Generic的控制表达式属于“未被求值使用”的场景,自然不在条款的强制要求范围内,并非标准条款遗漏了对_Generic的考量。
关于“否则”条款的解读
1. “否则”的指代对象
“否则”指代的是前面的触发条件不成立的情况,也就是:带外部链接的标识符没有被用于需要求值的表达式中(不满足条款开头的强制要求触发条件)。
2. 条款逻辑的冗余问题
你的错误解读源于对“否则”指代对象的误解,正确的条款逻辑拆分应该是:
- 触发条件成立(标识符被用于非例外的求值表达式):
ext_def_cnt == 1(必须恰好存在一个外部定义,不能缺失也不能重复) - 触发条件不成立(标识符未被这样使用):
ext_def_cnt <= 1(外部定义可以不存在,也可以存在一个,但绝对不能超过一个)
这样逻辑清晰且无冗余:前者是强制要求“存在且唯一”,后者是允许“不存在或唯一”,但都禁止重复定义。
内容的提问来源于stack exchange,提问作者pmor
相关产品推荐
相关产品推荐

