😸
次期C標準 (C23) の内容が固まったらしい
C23については最近のC言語と、次期C標準(C23)でも軽く紹介しました。
今回、C23入りする内容が大体固まったようなので改めて紹介します。
この記事を書いている時点での最新の公開されたWorking Draftは N2912 N3047 N3054 N3096です。ただし、C2y向けの最初のドラフトN3220もあり、そちらの方が実際の内容に近いかもしれません。
内容については会議参加者の投稿も参考にしています:
というわけで、C23に入る主な機能はこちらです:
C23に入る主な機能
- POSIXの機能の取り込み:
strdup,strndup,memccpy,gmtime_r,localtime_r - C++の機能の取り込み:
-
[[]]による属性:標準では[[nodiscard]],[[maybe_unused]],[[deprecated]],[[fallthrough]],[[noreturn]],[[_Noreturn]],[[reproducible]],[[unsequenced]]の8つ(実質7つ)。そのほかベンダー独自のもの[[vendor::attr]]も処理系次第で使える。 -
char8_t(ただしC++とは異なり、unsigned charのtypedef) -
u8文字リテラル(注:u8文字列リテラルはC11ですでに導入されている) - 定義済みの
bool,true,false,static_assert,alignof,alignas,thread_local - 1引数の
static_assert -
auto(N3007)- GCC等ではすでに
__auto_typeというキーワードでC++のautoみたいなやつが使えるようになっていました。マクロとかで便利なようです。Typeof (Using the GNU Compiler Collection (GCC))
- GCC等ではすでに
-
constexprによる定数。関数は不可。 (N3018) - 基礎となる型を指定した
enum(N3021) -
nullptr(N3019) - digit separator
- 二進数リテラル
-
= {}による初期化 (N2900)
-
- 浮動小数点数
- IEEE 754-2019への対応。これまではIEEE 754-1985を参照していた。
- TS 18661-1, TS 18661-2およびTS 18661-4の一部は本文に取り込まれ、TS 18661-3(
_FloatN型など)はAnnex Hとして取り込まれた(以前のAnnex HはLanguage Independent Arithmeticだった)。 - 追加される
#pragmaは#pragma STDC FENV_ROUND,#pragma STDC FENV_DEC_ROUNDなどです。
- K&Rスタイルの関数定義の廃止
- また、定義が伴わない関数宣言の仮引数リストが空の場合は「関数が引数を取らない」ことを表すようになります(N2841)。
- 必須の引数を持たない可変長引数関数を定義できるようになる(N2975)
-
va_startの二番目の引数はoptionalとなる。 - C++では以前から「必須の引数を持たない可変長引数関数の定義」ができ、SFINAEとかで活用されていましたが、
va_startを使えないため引数にアクセスすることはできませんでした。
-
- 2の補数表現が必須となる
-
#elifdef,#elifndef -
#embed(N3017)- ファイルの埋め込みができます。
#warning-
typeof(N2927)- C++の
decltypeは参照型に依存するため、C言語には持ってこれませんでした。 - キーワードにアンダースコアとかがつかないのは、各種コンパイラーが既に
typeofキーワードを提供しているし変数名に使っているやつはいないだろ、というアレがあるんでしょう(適当)。 -
N2927ではtypeofの他にremove_qualsというやつが入ります。一方でremove_qualsではなくunqual_typeofみたいな名前にしようぜ、という提案(N2930)もあり、結局どっちになったの?typeofの他にtypeof_unqualも入ります。
- C++の
-
unreachable()(N2826)- GCC/Clangの
__builtin_unreachable()とかMSVCの__assume(false)とかC++23のstd::unreachable()みたいなやつです。ある種の最適化に役立ちます。
- GCC/Clangの
_BitInt-
memset_explicit- 以前から似たようなやつにAnnex Kの
memset_sがありましたが、引数がちょっと違います。
- 以前から似たようなやつにAnnex Kの
- スタックに確保しない可変長配列(ポインターとか引数とか)は必須の機能に昇格されます。
- オーバーフローを検査する整数演算:
ckd_add,ckd_sub,ckd_mulin<stdckdint.h>(N2683) __has_include- popcountやclz, ctzなどのビット演算
<stdbit.h>:stdc_count_ones,stdc_leading_zeros,stdc_trailing_zerosなど(N3022の一部)
個々の機能についてここで詳しい説明をするといくら時間があっても足りません。いくつかについては私の書いた記事があります。
- C言語のbool型とその名前について 〜もう_Boolは嫌だ〜
-
C言語でのオーバーフロー検査(
<stdckdint.h>) - C23の新機能:高度なビット操作<stdbit.h>の紹介
- C23の改善点:文字列検索関数でのconst性の維持
他のいくつかについては、yohhoy氏の記事があるので紹介しておきます:
- C2x標準の属性(attribute) - yohhoyの日記
- #elifdefと#elifndef - yohhoyの日記
- 2進数リテラル in 標準C - yohhoyの日記
- realloc(ptr, 0)は廃止予定 - yohhoyの日記
- 2進数フォーマット出力 in 標準C - yohhoyの日記
- nullptr定数 in 標準C - yohhoyの日記
- reproducible/unsequenced属性 - yohhoyの日記
- typeof演算子 in 標準C - yohhoyの日記
- #embedディレクティブ - yohhoyの日記
- R.I.P. "= {0}" - yohhoyの日記
標準化委員会の中の人による記事も参考になります:
機能リストについてはcppreferenceの方にもまとまっているようです。
GCCの対応状況
最近のGCCでは一部の機能が -std=c2x で(GCC 14以降では -std=c23 でも)使えるようになっています。
- GCC 10 Release Series — Changes, New Features, and Fixes - GNU Project
- GCC 11 Release Series — Changes, New Features, and Fixes - GNU Project
- GCC 12 Release Series — Changes, New Features, and Fixes - GNU Project
- GCC 13 Release Series — Changes, New Features, and Fixes - GNU Project
- GCC 14 Release Series — Changes, New Features, and Fixes - GNU Project
GCC 10では
-
[[]]による属性:標準の[[deprecated]],[[fallthrough]],[[maybe_unused]]と、[[gnu::ホニャララ]] - UTF-8文字リテラル:
u8''
などが、GCC11では
-
<stdbool.h>で定義されるtrue,falseがbool型を持つようになった -
[[nodiscard]]属性 __has_c_attribute
などが、GCC12では
- digit separators
-
#elifdef,#elifndef
などが、GCC13では
nullptr-
enumの拡張 autoconstexpr-
typeof,typeof_unqual -
alignas,alignof,bool,false,static_assert,thread_local,trueのキーワード化 -
[[noreturn]]属性 = {}unreachable()- プロトタイプなし関数の削除
などが、GCC14では
_BitInt- 内容が同じstruct, union, enumを複数回定義できる
<stdckdint.h>
などが実装されています。
Clangの対応状況
Clangもバージョン9以降で -std=c2x によりC23の機能の一部が使えるようになっているようです。
この記事は随時アップデートしています。変更履歴はGitHubを見てください。
Discussion