关于C语言中标签名作用域起始位置的技术咨询
这个问题抓得非常准,N2176里这几段的表述确实容易让人绕进去,我来给你拆解清楚。
首先,咱们得先把标准里的几个关键段落的优先级理明白:标签是C语言里唯一拥有函数作用域的标识符,这是6.2.1第3段明确规定的,原文是:
A label name is the only kind of identifier that has function scope. It can be used (in a goto statement) anywhere in the function in which it appears, and is declared implicitly by its syntactic appearance (followed by a : and a statement).
这段已经把标签的核心规则说死了:它能在函数内的任何位置被goto引用,不管它的定义(也就是那个带:的标签行)写在函数的哪个地方。这就直接意味着它的作用域是覆盖整个函数体的——从函数开头到函数结尾。
那你纠结的第6.2.1第7段的规则,为什么和这个不冲突?因为那段的规则根本不适用于标签。咱们再看那段的开头:
except a struct tag, union tag, enumeration tag, and an enumeration constant, Any other identifier has scope that begins just after the completion of its declarator.
这里的“any other identifier”指的是除了前面列举的结构体/联合体/枚举标签、枚举常量之外,还没被前面段落单独定义作用域规则的标识符。而标签已经在第3段被单独定义了作用域,所以它不属于这个“any other”的范畴,自然不受第7段规则的约束。
举个实际的代码例子你就懂了:
void test() { goto jump_here; // 完全合法,虽然jump_here在后面才定义 // 中间一堆代码 jump_here: puts("到达标签位置"); }
这段代码能正常编译运行,就是因为标签的作用域是整个函数,哪怕你在标签定义之前用goto跳转,也是符合标准的。
总结一下:C语言里标签名的作用域起始于函数体的开头,结束于函数体的结尾,这是标准给标签开的特例,专门用来支持goto语句的灵活跳转,不用套普通标识符的作用域生效规则。
内容来源于stack exchange

