C言語/C23の変更点
2023年11月現在の最新のCの国際規格ISO/IEC 9899:2018(通称C17)は、ISO/IEC 9899:2011(通称C11)の不明確な部分を補うErrata的な規格で、実質的にC11が現行の最新規格という状態が10年以上続いています。
このような中、
ここでは、現在入手可能な working draft — September 3, 2022 ISO/IEC 9899:2023 (E)N3054,N3096[2]に基づいて、C23のC11に対する変更点をまとめます。
ハイライト[編集]
C23の変更点のうちでも目立ったものを列挙します[3]。
キーワードに昇格したマクロ[編集]
bool
,static_assert
,true
,false
,thread_local
がマクロからキーワードに昇格しました。
また、新旧のキーワードをマクロとして定義することで、プログラムの移行を容易にすることができるようになりました。
多くの _ で始まるキーワードがマクロになりましたが、全てではありません。
整数は二の補数表現が必須[編集]
整数の幅の制約と時代遅れの符号表現(いわゆる「1の補数」と「符号-マグニチュード」)を削除しました。
static_assertの一引数版[編集]
static_assert
の第二引数はオプショナルになりました。
プロトタイプ宣言が必須化[編集]
識別子リストによる関数定義のサポートを削除しました。
空の引数リストの意味がC++と同じに[編集]
関数宣言の引数リストが空の場合、voidを1つだけ含む引数リストと同じように扱うことが義務付けられました。
ISO/IEC 9945 (POSIX)との整合性の向上[編集]
strftime[編集]
拡張月名フォーマット追加
関数の統合[編集]
gmtime_r
, localtime_r
, memccpy
, strdup
, strndup
を統合。
浮動小数点規格IEC 60559との整合性の向上[編集]
- バイナリ浮動小数点技術仕様 TS 18661-1 の統合
- 10進浮動小数点技術仕様書 TS 18661-2 の統合
- 数学関数技術仕様書 TS 18661-4a の統合
DECIMAL_DIG廃止[編集]
最高精度の浮動小数点数を有効数字すべてを表現するために必要な 10 進数字の最小桁数を表すマクロ DECIMAL_DIG が廃止されました。DR 501
ライブラリーヘッダーにバージョンテスト用マクロを追加[編集]
アップグレードや移植を支援するための変更を含むライブラリヘッダーに、バージョンテスト用マクロが追加されました。 この機能がサポートされていること自身を、まず STDC_VERSION__ マクロで確認する必要があります。
ラベル配置可能位置の拡大[編集]
宣言の前や複合文の末尾にラベルを配置できるようにしました。
属性を含むアトリビュート機能を追加[編集]
- deprecated
- 将来使用しないことを示すエンティティをマークする。
- fallthrough
- switchやlabelのフォールスルーが偶発的ではなく、意図的である場合を明示的にマークする。
- maybe_unused
- 最終的に使用されないかもしれない実体をマークする。
- nodiscard
- 使用された場合、その値がプログラムによって何らかの方法で処理されるべきエンティティをマークする。
- reproducible
- (再現可能)同じ入力が与えられると常に予測可能な出力を生成する関数タイプ(例えば、キャッシュされたデータ)をマークするため、しかしそのような関数の呼び出しの順序は依然として重要である。
- unsequenced
- 常に予測可能な出力を生成し、他のデータへの依存性がない関数タイプ(およびその他の関連する注意事項)をマークするためのものです。
- noreturn
- 関数が決して戻ってこないことを示す。
u8文字プリフィックス[編集]
u8文字列プリフィックスとの整合性の為、u8文字プリフィックスが追加されました。
u8, u, U文字列のエンコードの規格化[編集]
u8,u,Uをプリフィックスとする文字列を、それぞれ ISO/IEC 10646で定義された UTF-8,UTF-16,UTF-32とすることをが義務付けられました。
エンコーディングの分離[編集]
文字列と文字のためのリテラル、ワイドリテラル、UTF-8リテラル、UTF-16リテラル、UTF-32リテラルエンコーディングを分離し、これらの実行ベースバージョン、特に実行とワイド実行エンコーディングを単独で持つようになりました。
uchar.hに関数を追加[編集]
ヘッダー<uchar.h> に欠落していた mbrtoc8 と c8rtomb 関数が追加されました。
複合リテラルのライフタイムの変更[編集]
複合リテラル( compound literals )には、型の一部としてストレージクラス指定子を含めることができ、複合リテラルのライフタイムを変更することができます。 複合リテラルのライフタイムを変更する(定数式に変更する場合もある)。
constexpr[編集]
オブジェクト定義に constexpr 指定子を追加し、constexpr ストレージクラス指定子と組み合わせて定数式として認識される内容が改善されました。
typeofとtypeof_unqual[編集]
式の型を推論するtypeofとtypeof_unqual演算子が追加されました。
タグの互換性ルールの改善[編集]
タグの互換性ルールに若干の変更が加わり、既存の矛盾を解消し、マクロを用いた汎用的なプログラミングを容易にし、代数的な型の構築を可能にすることができるようになりました。N2863 N2366 N2105
ビット精度の整数型 _BitInt の追加[編集]
ビット精度の整数型 _BitInt が追加されました。この型の顕著な特性の1つは、性能上の理由から、デフォルトの整数プロモ ーションが行われないことです。 リテラル・サフィックス wb を使用することで、_BitInt とリテラルを含む式の不要な変換をさらに減らすことができます。N2960 N2946 N2775 N2709 N2646
enum の基礎となる型が指定可能に[編集]
列挙型に基礎となる型を指定する機能が追加されました。 これによって、int よりも大きな範囲の値表現を持つことができるようになりました。
enum Colour : char { Red, Green, Blue };
stdbit.h[編集]
ヘッダー <stdbit.h> が追加されました。 ビットおよびバイトを扱う一連のユーティリティを追加し、多くの実装の最も効率的な機能へポータブルにアクセスできるようにしました。
QCharやQVoidの導入[編集]
既存関数の宣言を変更し、関数内に配置された型の定数性( const-ness )を保持するようになりました。N2973
QVoid *memchr(QVoid *s, int c, size_t n); QChar *strchr(QChar *s, int c);
この変更は、Nプロポーザル N2522, 2603およびN2973 で提案されました。
この提案は、C標準ライブラリに含まれる12の検索関数(bsearch bsearch_s memchr strchr strpbrk strrchr strstr wcschr wcspbrk wcsrchr wcsstr wmemchr)が、const修飾子を失うという問題を解決するものです。これらの関数は、検索されるバッファへのconst修飾ポインタを受け取りますが、const修飾を失ったポインタを返します。提案では、これらの関数が、入力バッファの修飾子と同じ修飾子を持つ要素を返すことが明示的に指定されるべきであるとされています。つまり、ユーザーが指定した修飾子と同じ修飾子を持つ要素を返すことで、入力バッファのconst修飾を無意識に失うことを防ぐことができます。
提案の根拠として、既存のAPIはC11がジェネリックでオーバーロードされた関数の定義を導入する前に設計され、ライブラリに追加されました。したがって、入力パラメータには暗黙的にconst修飾を追加することができるため、const修飾されたバッファと変更可能なバッファの両方を検索することができるように、既存のシグネチャが設計されました。正しく使用されれば、返されるポインタの修飾が不足している場合でも、適切に修飾された結果ポインタに割り当てることで、同じ修飾が復元されます。これにより、検索関数はジェネリックな機能を提供する原始的な形式を提供します。
しかし、ユーザーが返されたポインタの変数が正しいタイプであることを手動で確認する必要があります。ユーザーがconst修飾されたバッファを検索して、結果を変更可能なオブジェクトのポインタに割り当てた場合、APIには直接的にこれがタイプエラーであることを伝える方法がありません。実装によっては、警告を表示することができるかもしれませんが、これは言語で伝えられるものを超えて、ライブラリ関数とその契約に関するハードコーディングされた知識を必要とするでしょう。
#embed[編集]
プリプロセッサディレクティブ #embed
が追加された。
バイナリーデーターを可能な限り忠実に埋め込む機能
nullptr定数とnullptr_t型を追加[編集]
nullptr定数とnullptr_t型が追加されました。 voidへのポインタと同じように定義された基本表現を持ちます。N3042
__VA_OPT__[編集]
__VA_OPT__ は、マクロのパラメーターとして受け取った可変引数が空でない場合に置換するトークンを指定します。C++20
可変モディファイ型のサポートが義務化[編集]
可変モディファイ型( Variably-Modified Types )のサポートを義務付けられました(ただし、可変長配列そのものではありません)。N2992
void foo(int n, double (*x)[n]) { (*x)[n] = 1; // 無効なアクセスは実行時に検出することができます // (場合によっては、より強力な解析によりコンパイル時にも検出可能) }
関数の第一引数に ... が使用可能に[編集]
関数定義の引数の省略記号( ... )は、関数のパラメーターリストにおいて先行するパラメータなしで現れることができるようになりました。 va_startはもはやそのような引数が渡されることを必要としません。
Unicode 識別子更新[編集]
Unicode 識別子が、UAX(Unicode Standard Annex) #31 に従うようになりました。
[編集]
[編集]
[編集]
[編集]
[TODO:#ハイライトの完成]
C23の変更点[編集]
文書番号 | タイトル | 概要 |
---|---|---|
N2432 | Remove support for function definitions with identifier lists 旧式の関数定義の廃止 |
ANSI Cのプロトタイプ宣言以前の、K&R1形式の関数宣言が廃止されました。 |
N2940 | Remove Trigraphs??! トリグラフの削除 |
# を ??= の3文字で表すトリグラフ(JIS語では「3文字表記」)が規格から削除されました。C++では既にC++17で削除されています。
|
N2412 | Two’s complement sign representation for C2x 符号付き整数の形式は二の補数に限定 |
「C言語から2の補数以外の符号表現を削除することで、整数型の仕様を大幅に簡素化することができる」とし「他の符号表現の仕様」を排除しました。 |
N2549 | Binary Literals 二進数リテラル |
二進数リテラルが追加されました。二進数リテラルは、接頭辞0bまたは0Bの後に0または1の数字が連続したものです。C++では既にC++14で二進数リテラルが導入されています。 |
N2612 | Formatted input/output of binary integer numbers 二進整数の書式付き入出力 |
二進数リテラルに呼応する形でprintf系とscanf系の関数に書式 %b が追加されました。 |
N2335 | Attributes in C 属性 |
属性に関する構文と属性の種類が規格化されました。 |
N3007 | Type inference for object definitions 型推論 |
オブジェクト定義に於ける型推論が規格化されました。 |
旧式の関数定義の廃止[編集]
ANSI Cのプロトタイプ宣言以前の、K&R1形式の関数宣言が廃止されました。
- K&R1形式の main()
#include <stdio.h> int main(argc, argv) int argc; char *argv[]; { printf("Hello world!\"); }
トリグラフの削除[編集]
#
を ??=
の3文字で表すトリグラフ(JIS語では「3文字表記」)が規格から削除されました。C++では既にC++17で削除されています。
符号付き整数の形式は二の補数に限定[編集]
「C言語から2の補数以外の符号表現を削除することで、整数型の仕様を大幅に簡素化することができる」とし「他の符号表現の仕様」を排除しました。
二進数リテラル[編集]
二進数リテラルが追加されました。二進数リテラルは、接頭辞0bまたは0Bの後に0または1の数字が連続したものです。C++では既にC++14で二進数リテラルが導入されています。
二進整数の書式付き入出力[編集]
二進数リテラルに呼応する形でprintf系とscanf系の関数に書式 %b が追加されました。
属性[編集]
属性( attribute )は、一般化された構文を持つ言語エンティティに、開発者が各機能のために新しい構文やキーワードを導入する代わりに、追加の情報を付加できるメカニズムです。
[TODO:具体例]
型推論[編集]
型推論( Type inference; TI )とは、宣言がその初期化子として使用される式から型を推論することを可能にする機能です。
N3007提案では、auto i = 123L;
の様に「型」の部分に auto
と書くと初期化子(この場合は 123L)から変数(この場合は i)の型(この場合は long)を言語処理系が推論するという構文です(概ねC++と同じですが、C++には参照やラムダ式があるので若干事情が違います)。
auto
は今までもキーワードでしたが、(静的変数に対して)「自動変数」を宣言することを表すもので、省略可能でした。
- auto-example.c
#include <stdio.h> #include <stdlib.h> int main() { auto file = fopen("/etc/hosts", "r"); if (file == NULL) { perror("Error opening file"); return 1; } // ファイルから1行ずつ読み込んで標準出力に表示 char line[256]; while (fgets(line, sizeof(line), file)) { printf("%s", line); } fclose(file); return 0; }
auto file = fopen("/etc/hosts", "r");
は、これまでならば
FILE *file = fopen("/etc/hosts", "r");
と書くところですが、型推論を使って明示的な型名を記さないで済ませています。
脚註[編集]
- ^ N3054によると、__STDC_VERSION__ は 202311L となるようです。
- ^ C23 now finalized!
- ^ N3096 Annex M (informative) Change History
外部リンク[編集]
- ISO/IEC WG 14 Document Log. ISO/IEC. (2022-09-29) .
- C2x: N3054 working draft — September 3, 2022 ISO/IEC 9899:2023 (E). ISO/IEC. (2022-09-03) .
- ISO/IEC 9899:2018(en) Information technology — Programming languages — C. ISO/IEC. (2018-07-05) .
- N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. オリジナルの2018-12-30時点によるアーカイブ。 .