属性(C23)
C23 引入了属性说明符序列 (Attribute specifier sequence),语法为 [[...]]。它提供了一个统一的标准语法,用于表达实现定义的语言扩展(例如 GNU 的 __attribute__、MSVC 的 __declspec),并且也定义了一小组标准属性。
1. 语法概览
属性说明符序列的基本形式是:
[[attribute]][[attr1, attr2]][[attr("reason")]](带实参)[[vendor::attr]](带命名空间前缀)
未知属性会被忽略
实现不认识的属性会被忽略,并且不会报错。因此,属性是“可选增强”:它们可以提升诊断质量或优化机会,但不应成为程序正确性的前提。
2. 标准属性(C23)
C 标准定义了如下标准属性;同时,每个标准属性名 attr 也允许写成 __attr__,语义不变。
2.1 [[deprecated]]
标记某个名字/实体“允许使用但不推荐使用”,编译器可以对此产生警告。
c
[[deprecated("use new_api instead")]] int old_api(void);1
2.2 [[fallthrough]]
用于 switch 中表明“从上一个 case 贯穿到下一个 case 是有意的”,用于抑制编译器的 fall-through 警告。
c
int f(int x) {
switch (x) {
case 1: {
/* ... */
[[fallthrough]];
}
case 2: {
return 2;
}
default: {
return 0;
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
2.3 [[nodiscard]]
鼓励编译器在返回值被丢弃时产生警告。
c
[[nodiscard]] int parse(void);
int main(void) {
parse(); /* 可能触发警告:丢弃返回值 */
return 0;
}1
2
3
4
5
6
2
3
4
5
6
2.4 [[maybe_unused]]
用于抑制“未使用实体”的警告(若实现有这类警告)。
c
[[maybe_unused]] static int debug_flag = 0;1
2.5 [[noreturn]]
标记一个函数“不返回到调用者”。C11 也有 _Noreturn 函数说明符;C23 另外提供 [[noreturn]] 属性(并保留 [[ _Noreturn ]] 这一兼容拼写,但它已被弃用)。
c
[[noreturn]] void panic(void);1
2.6 [[unsequenced]] 与 [[reproducible]]
这两者用于表达函数在副作用与可重复性方面的性质,帮助编译器进行更激进的优化:
[[unsequenced]]:函数是无状态、无副作用、幂等,并且相互独立。[[reproducible]]:函数无副作用且幂等。
3. 属性测试:__has_c_attribute
如果你希望在不同编译器/标准库支持度下有条件使用属性,C23 提供了 __has_c_attribute(attribute-token),可用于 #if / #elif 的条件表达式中。
4. 习题
- 给你项目里一个准备废弃的函数加上
[[deprecated("...")]],并在说明文字里写出替代 API。 - 写一个
switch,刻意包含一次 fall-through,并用[[fallthrough]];标注它。 - 找一个“必须检查返回值”的函数(例如解析/打开文件),给它加上
[[nodiscard]],并验证编译器是否给出诊断。