(C23/C++23) 语句末尾的标签

🔖前言

🏷️ref

在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值