🔖前言
🏷️ref
- C++23提案·复合语句末尾的标签
- C23提案·声明和语句块结束前的标签
在C/C++的标签使用语法中,两们语言的规定并不是一致的。很容易产生写法A在C语言中可行,而C++中不行。(虽然部分编译器做了增强,但标准中就是不行)。
但非常幸运的是两者都在23标准中互相做了兼容。
个人猜测是那帮专家自己写要兼容的代码时觉得非常麻烦而提出的。
因为标签的意义就是一个表示,且表示非常明确,编译器理应本身就能做区分。
🏷️标号
任何语句都能有标号,通过在语句自身前提供一个跟随冒号的名称。
任何语句(但非声明)可以前附任意数量的标号,每个都声明一个 标识符 为标号名,标号名必须在闭合的函数中唯一(换言之,标号名拥有函数作用域)。
标号声明自身没有效果,不会以任何方式变更控制流,或修改跟随其后的语句的行为。
🔖兼容
🏷️23标准前
下面是一个典型的例子。此代码特指两者在23标准前的情况。
demo.c & demo.cpp
/* C23 C++23 标准之前 */
void foo(void) {
/* C++ 允许 */
/* C 不允许 */
first:
int x;
/* C++ 允许 */
/* C 允许 */
second:
x = 1;
/* C++ 不允许 */
/* C 不允许 */
last:
}
尝试编译测试:
测试环境
当然笔者这里的gcc本身就不支持23标准。
$ gcc --version
gcc (x86_64-posix-seh-rev3, Built by MinGW-W64 project) 11.2.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C语言
gcc -pedantic -ansi -std=c17 -c demo.c
demo.c: In function 'foo':
demo.c:6:5: warning: a label can only be part of a statement and a declaration is not a statement [-Wpedantic]
6 | int x;
| ^~~
demo.c:15:1: warning: label at end of compound statement [-Wpedantic]
15 | last:
| ^~~
C++
g++ -pedantic -ansi -std=c++20 -c demo.cpp
demo.cpp: In function 'void foo()':
demo.cpp:16:1: error: expected primary-expression before '}' token
16 | }
| ^
🏷️23标准后
没啥可说的,就是上面的情况在 C23/C++23
后都允许。
🏷️原因
摘自P2324R2
。
In C declarations and statements are separate production rules which can both appear as block-items inside compound statements.
The simplest change for C was to also allow labels as independent block-items in addition to statements and declarations.
This change then also allowed placing labels at the end of a compound statement which was seen as useful feature.
在C语言中,声明和语句是独立的生成规则,它们都可以作为复合语句中的块项出现。
对于C来说,最简单的改变是除了语句和声明之外,还允许标签作为独立的块项。
这个变化还允许在复合语句的末尾放置标签,这被认为是一个有用的特性。
In C++ declarations are statements and compound statements can only have statements as block-items.
Thus, labels can already be attached to all statements, i.e. including declarations, but can not be placed at the end of compound statements.
Another difference is that in C++ (but not in C) it is possible to use declarations as sub-statements of a control statements.
The later seems to be an unintended side effect of making declarations be statements and now requires a rewrite rule to place this declaration into a new scope.
在c++中,声明是语句,复合语句只能有语句作为块项。
因此,标签可以附加到所有语句,即包括声明,但不能放在复合语句的末尾。
另一个区别是,在c++(而不是C)中,可以将声明用作控制语句的子语句。
后者似乎是使声明成为语句的意外副作用,现在需要重写规则将该声明放入新的作用域。
🔖未兼容
来看另一个例子。
该例子在C++中式可行的,但在C语言中,即使到了C23还是不可行。
因此对于该情况,还是要添加大括号构成块级作用域规范些。
void bar(void) {
/**
* C++ 可行
* C 不可行 (C23 仍不可行)
*/
if (1)
here:
int x;
}
🔖END
上文代码的在线示例:https://godbolt.org/z/6MEdTheG9
🌟关注我
关注我,学习更多C/C++,算法,计算机知识
B站:
👨💻主页:天赐细莲 bilibili