yohhoyの日記

技術的メモをしていきたい日記

C2x標準の属性(attribute)

プログラミング言語Cの次期仕様C2x(C23)では 属性(attribute) 構文が標準化される。属性構文を先行導入したC++言語とほぼ等価であり、連続するブラケット[[]]を用いる。*1

// C2x
[[nodiscard]] int f();

void g([[maybe_unsed]] int a) {
  [[maybe_unused] int x;
  /* ... */
}

struct [[deprecated("old ver.")]] S {
  /*...*/
};

int n = f();
switch (n) {
case 0:
case 1:
  f();
  [[fallthrough]];
default;
  g(n);
  break;
}

属性指定を行える箇所:

  • 構造体(struct)/共用体(union)の型宣言
  • 列挙型(enum)の型宣言
  • 列挙子(enumerator)の定義
  • 変数/関数仮引数の宣言
  • 関数の宣言/定義
  • 任意の文(statement)

2020年2月時点のC2xドラフト*2で追加される属性は下記4種類
2022-08-07追記:Feature Freeze版とされる2022年8月時点のC2xドラフト*3で追加される属性は下記7種類*4

  • nodiscard(→(PDF) N2267
    • 2021-02-28追記:(PDF) N2448 nodiscard("should have a reason") も採択済み。
  • maybe_unused(→(PDF) N2270
  • deprecated, deprecated("string-literal")(→(PDF) N2334
  • fallthrough(→(PDF) N2408
  • 2022-07-26追記:noreturn, _Noreturn(→(PDF) N2764
    • C11で導入された<stdnoreturn.h>標準ヘッダ、_Noreturn関数指定子(function specifier)、およびC2xの_Noreturn属性ともに廃止予定(obsolescent feature)とされる。
  • 2022-08-07追記:reproducible, unsequenced(→N2956)(→id:yohhoy:20220909

C++属性構文との共通点/差分:

  • C++同様に、処理系定義(implementation-defined)の属性を許容する。未知の属性は無視される。
  • C++同様に、処理系定義の属性用に名前空間(相当)を指定できる。*5
  • C2xの属性attrは前後にアンダースコア2つを追加した__attr__と同義。例:[[nodiscard]][[__nodiscard__]]は同じ属性を表す。
  • 2021-07-17追記:属性の重複指定を許容する(→(PDF) N2557)。C++2b(C++23)側もWG21 N2156R1を採択予定。
  • 2022-08-07追記:__has_c_attribute機能テストマクロ(→(PDF) N2553
    • C++20__has_cpp_attribute機能テストマクロのC言語版。*6

関連URL

*1:C2x/C++いずれの言語仕様でも新規トークン [[ や ]] は導入せず、“ブラケット [ または ] が2トークン連続(空白を挟んでもよい)” を属性の開始/終了として扱う。

*2:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2478.pdf

*3:https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf

*4:いずれもプログラム意味論には影響を与えず、標準属性を無視してもプログラム動作は変化しない。それぞれC2x標準属性のサポートは処理系定義のオプションとされるが、各処理系は標準属性を実装することが推奨(recommended)される。

*5:C言語には名前空間(namespace)が存在しないため、属性構文でのみ利用する専用の構文要素 attribute-prefix とコロン2つからなる新しいトークンを導入している。┐(´-`)┌

*6:https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0941r2.html