2024年6月現在の最新のCの国際規格ISO/IEC 9899:2018(通称C17)は、ISO/IEC 9899:2011(通称C11)の不明確な部分を補うErrata的な規格で、実質的にC11が現行の最新規格という状態が10年以上続いています。

このような中、ISO(国際標準化機構)/()IEC(国際電気標準会議) ()JTC 1(第一合同技術委員会)/SC 22(プログラミング言語標準化副委員会) WG14(Cワーキンググループ) は、ISO/IEC 9899:2023(通称C2xまたはC23)を2023年11月を目標に策定していますN2984, N3132, (WG 14 Document Log)[1]

ここでは、現在入手可能な working draft — September 3, 2022 ISO/IEC 9899:2023 (E)N3054,N3096[2]に基づいて、C23のC11に対する変更点をまとめます。

C23の新機能と変更点

編集

属性の規格化

編集
規格の文章(C23)
  1. The attribute feature was introduced in the fifth edition of this document, as detailed in the change list in M.2. The following table illustrates what usage of the __has_c_attribute preprocessor conditional expression should return in the latest revision, previous values, and the change associated with that value.
  2. Programs and implementations may use this table to know what values were being used at any specific point in time, leading up to the publication of this document. The value at the bottom of a particular row in a table is the latest value and corresponds with the behavior for the given attribute described in this document.
解説
C23では、属性( attribute )の機能が導入されました。属性は、一般化された構文を持つ言語エンティティに、開発者が各機能のために新しい構文やキーワードを導入する代わりに、追加の情報を付加できるメカニズムです。__has_c_attribute プリプロセッサ条件式が新しい属性のサポートをチェックするために使用されます。
具体例
以下のコードは、deprecated 属性がサポートされているかどうかをチェックします。
#if __has_c_attribute(deprecated)
[[deprecated]] void old_function();
#endif
新しい属性の詳細
属性トークン 変更点
deprecated 201904L 初期導入
202311L 第五版で調和
fallthrough 201904L 初期導入
201910L ブロックの仕様改善により診断位置を拡張
202311L 第五版で調和
maybe_unused 201904L 初期導入
202106L ラベルにも適用可能
202311L 第五版で調和
nodiscard 201904L 初期導入
202003L 診断目的で文字列リテラルを受け取る形式を追加
202311L 第五版で調和
noreturn 202202L 初期導入
202311L 第五版で調和
reproducible 202207L 初期導入
202311L 第五版で調和
unsequenced 202207L 初期導入
202311L 第五版で調和
解説
新しい属性はコードの可読性と安全性を向上させるために導入されました。例えば、nodiscard 属性は、関数の戻り値を無視することを防ぐために使用されます。
具体例
nodiscard 属性の使用例:
[[nodiscard]] int compute_value() { return 42; }

int main() {
    compute_value();  
// nodiscard1.c:4:5: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
}

新しいキーワードと古いキーワードへの互換性

編集
規格の文章(C23)
  1. Major changes in this fifth edition (__STDC_VERSION__ 202311L) include:
    — added new keywords such as bool, static_assert, true, false, thread_local and others, and allowed implementations to provide macros for the older spelling with a leading underscore followed by a capital letter a
解説
C23では bool, static_assert, true, false, thread_localなどの新しいキーワードが追加されました。
コンパイラは、古いスペル (アンダースコアに続いて大文字) のマクロを提供したり、新旧のキーワードをマクロとして定義することで、既存プログラムの移行を容易にすることもできます。
多くの _ で始まるキーワードがマクロになりましたが、全てではありません。
具体例
新しいキーワードの使用例:
#include <assert.h>
#include <stdbool.h>

void example() {
    bool flag = true;
    static_assert(sizeof(int) == 4, "int size is not 4 bytes");
    assert(flag);
}

整数の表現方法が標準化

編集
規格の文章(C23)

— removed integer width constraints and obsolete sign representations (so-called "1’s complement" and "sign-magnitude");

解説
整数の幅の制約と、時代遅れになった符号表現 (いわゆる "1の補数" と "符号と絶対値") が削除されました。

単一引数バージョンのstatic_assertの追加

編集
規格の文章(C23)

— added a one-argument version of static_assert;

解説
static_assert の単一引数バージョンが追加されました。

旧式の関数定義の廃止

編集
規格の文章(C23)

— removed support for function definitions with identifier lists;

解説
関数定義における識別子リストによる定義がサポートされなくなりました。N2432 N2770
K&R1形式の main()
#include <stdio.h>

int main(argc, argv)
    int argc;
    char *argv[];
{
    printf("Hello world!\");
}

関数宣言におけるからのパラメータリストの許容

編集
規格の文章(C23)

— mandated function declarations whose parameter list is empty be treated the same as a parameter list which only contain a single void;

解説
パラメータリストが空の関数宣言は、空のパラメータリストを持つ関数宣言と同じように扱われるようになりました。

POSIXとの調和

編集
規格の文章(C23)

— harmonization with ISO/IEC 9945 (POSIX):

  • extended month name formats for strftime
  • integration of functions: gmtime_r, localtime_r, memccpy, strdup, strndup
解説
C23はPOSIX(ISO/IEC 9945)との整合性を強化しました。例えば、strftime の月名形式が拡張され、gmtime_rlocaltime_rmemccpystrdupstrndup の関数が統合されました。
具体例
POSIXとの整合性を示す例:
#include <math.h>
#include <stdio.h>

void example() {
    double max_value = fmax(3.0, 4.0);
    double min_value = fmin(3.0, 4.0);
    printf("Max: %f, Min: %f\n", max_value, min_value);
}

浮動小数点標準(ISO/IEC 60559)との整合性

編集
規格の文章(C23)

— harmonization with floating-point standard ISO/IEC 60559:

  • integration of binary floating-point technical specification TS 18661-1
  • integration of decimal floating-point technical specification TS 18661-2
  • integration of floating-point types technical specification TS 18661-3
  • integration of mathematical functions technical specification TS 18661-4a
  • new maximum and minimum functions for operations recommended in ISO/IEC 60559:2020
解説
浮動小数点標準(ISO/IEC 60559)との整合性が強化され、様々な技術仕様が統合されました。

これには、バイナリおよびデシマル浮動小数点、浮動小数点型、および数学関数に関する技術仕様が含まれます。

  • バイナリ浮動小数点技術仕様 TS 18661-1 の統合
  • 10進浮動小数点技術仕様書 TS 18661-2 の統合
  • 数学関数技術仕様書 TS 18661-4a の統合
具体例
新しい最大値および最小値関数の使用例:
#include <math.h>
#include <stdio.h>

int main() {
    double max_value = fmax(3.0, 4.0);
    double min_value = fmin(3.0, 4.0);
    printf("Max: %f, Min: %f\n", max_value, min_value);
}

DECIMAL_DIG廃止

編集
規格の文章(C23)

— made the DECIMAL_DIG macro obsolescent;

解説
最高精度の浮動小数点数を有効数字すべてを表現するために必要な 10 進数字の最小桁数を表すマクロ DECIMAL_DIG が廃止されました。DR 501

ライブラリーヘッダーにバージョンテスト用マクロを追加

編集
規格の文章(C23)

— added version test macros to library headers that contained changes to aid in upgrading and portability to be used alongside the __STDC_VERSION__ macro;

解説
アップグレードや移植を支援するための変更を含むライブラリヘッダーに、バージョンテスト用マクロが追加されました。
この機能がサポートされていること自身を、まず STDC_VERSION__ マクロで確認する必要があります。

ラベル配置可能位置の拡大

編集
規格の文章(C23)

— allowed placement of labels in front of declarations and at the end of compound statement;

解説
宣言の前や複合文の末尾にラベルを配置できるようにしました。

属性を含むアトリビュート機能を追加

編集
規格の文章(C23)

— added the attributes feature, which includes the attributes:

  • deprecated, for marking entities as discouraged for future use;
  • fallthrough, for explicitly marking cases where falling through in switches or labels is intended rather than accidental;
  • maybe_unused, for marking entities which may end up not being used;
  • nodiscard, for marking entities which, when used, should have their value handled in some way by a program;
  • noreturn, for indicating a function shall never return;
  • reproducible, for marking function types for which inputs may always produce predictable output if given the same input (e.g. cached data) but for which the order of such calls still matter; and,
  • unsequenced, for marking function types which always produce predictable output and have no dependencies upon other data (and other relevant caveats);
解説
新しい属性はプログラムの安全性と明確性を高めるために追加されました。これらの属性により、特定の使用が推奨されない関数や、意図的なフォールスルー、未使用の可能性があるエンティティなどをマークできます。
  • 属性機能が追加されました。属性には以下のようなものが含まれます。
    • deprecated: 将来的に非推奨とされるエンティティをマークする
    • fallthrough: switch やラベルでのフォールスルーが意図的なものであることを明示的に示す
    • maybe_unused: 使用されなかった可能性があるエンティティをマークする
    • nodiscard: 使用されたときに、プログラム内でその値が何らかの処理をされるべきであることを示す
    • noreturn: 関数が決してreturnしないことを示す
    • reproducible: 同じ入力を与えれば常に予測可能な出力を生成する関数型 (例えば、キャッシュされたデータ) をマークするものですが、このような関数の呼び出し順序は依然として重要です。
    • unsequenced: 常に予測可能な出力を生成し、他のデータに依存関係を持たない関数型をマークするもの (その他関連する注意点あり)
具体例
fallthrough 属性の使用例:
void example(int value) {
    switch (value) {
        case 1:
            // 何かの処理
            [[fallthrough]];
        case 2:
            // フォールスルーを意図的に許可
            break;
        default:
            break;
    }
}

u8文字プリフィックス

編集
規格の文章(C23)

— added the u8 character prefix to match the u8 string prefix;

解説
 u8文字列プリフィックスとの整合性の為、u8文字プリフィックスが追加されました。

u8, u, U文字列のエンコードの規格化

編集
規格の文章(C23)

— mandated all u8, u, and U strings be UTF-8, UTF-16, and UTF-32, respectively, as defined by ISO/IEC 10646;

解説
u8,u,Uをプリフィックスとする文字列を、それぞれ ISO/IEC 10646( Universal Coded Character Set )で定義された UTF-8,UTF-16,UTF-32とすることがが義務付けられました。

エンコーディングの分離

編集
規格の文章(C23)

— separated the literal, wide literal, and UTF-8 literal, UTF-16 literal, and UTF-32 literal encodings for strings and characters and now have a solely execution-based version of these, particularly execution and wide execution encodings;

解説
文字列と文字のためのリテラル、ワイドリテラル、UTF-8リテラル、UTF-16リテラル、UTF-32リテラルエンコーディングを分離し、これらの実行ベースバージョン、特に実行とワイド実行エンコーディングを単独で持つようになりました。

uchar.hに関数を追加

編集
規格の文章(C23)

— added mbrtoc8 and c8rtomb functions missing from <uchar.h>;

解説
ヘッダー<uchar.h> に欠落していた mbrtoc8c8rtomb 関数が追加されました。

複合リテラルのライフタイムの変更

編集
規格の文章(C23)

— compound literals may also include storage-class specifiers as part of the type to change the lifetime of the compound literal (and possibly turn it into a constant expression)

解説
複合リテラル( compound literals )には、型の一部としてストレージクラス指定子を含めることができ、複合リテラルのライフタイムを変更することができます。

複合リテラルのライフタイムを変更する(定数式に変更する場合もある)。

constexpr

編集
規格の文章(C23)

— added the constexpr specifier for object definitions and improved what is recognized as a constant expression in conjunction with the constexpr storage-class specifier;

解説
C23のconstexprは、新たに導入されたストレージクラス指定子であり、オブジェクトの値をコンパイル時に固定するために使用されます。以下はその主な制約と意味です:
  • constexprで宣言されたオブジェクトやそのメンバーは、アトミック型、可変修飾型、またはvolatilerestrict修飾子を持つ型を持つことができません。
  • 浮動小数点数型の初期化子は、翻訳時の浮動小数点環境で評価されなければなりません。
  • constexprで宣言されたポインタ、整数、算術型のオブジェクトは、それぞれnull、整数定数式、算術定数式、または浮動小数点数のいずれかで初期化されなければなりません。
  • constexprで宣言されたオブジェクトの値は、コンパイル時に永久的に固定されます。
  • constexprで宣言されたオブジェクトは、暗黙的に定数修飾されます。
constexprはコンパイル時の計算や値の固定化に役立ちます。

空の中括弧{}の初期化のサポートの追加

編集
規格の文章(C23)

— added support for initialization of objects with empty braces;

解説
C++と同様に、空の中括弧{}を用いたオブジェクトの初期化がサポートされるようになりました。
空の中括弧{}の初期化の概要
C23では、空の中括弧{}を使用してオブジェクトを初期化することができます。これは、特定の値を指定せずにオブジェクトをデフォルト値で初期化する方法です。
主な利点
簡潔さと可読性:
コードがより簡潔になり、可読性が向上します。初期化のための明示的な値を指定する必要がないため、特に大きな構造体や複雑な型の初期化において役立ちます。
デフォルト初期化:
すべてのメンバーがデフォルト値(通常は0またはNULL)に初期化されます。これにより、意図しない未初期化のバグを防ぐことができます。

typeofとtypeof_unqual

編集
規格の文章(C23)

— added the typeof and typeof_unqual operations for deducing the type of an expression;

解説
typeof および typeof_unqual は、C言語の新しい演算子です。

これらの演算子は、指定された式や型名に基づいて、型情報を取得するために使用されます。

以下に、それぞれの演算子の概要を説明します:
typeof
  • typeof 演算子は、指定された式または型名の型を取得します。
  • 式が与えられた場合、その式の型が返されます。
  • 型名が与えられた場合、その型の情報が返されます。
  • 例えば、typeof(1 + 1) は式 1 + 1 の型を取得します。
typeof_unqual
  • typeof_unqual 演算子は、typeof 演算子と同様に動作しますが、修飾を削除した型情報を返します。
  • つまり、constvolatile などの修飾子が削除された型情報が返されます。
  • 例えば、typeof_unqual(const int)int の型情報を返します。
これらの演算子は、特にマクロの定義や、型を動的に取得する必要がある場合などに役立ちます。

typeof 演算子は C 言語の柔軟性を高め、より効率的なコードを記述するのに役立ちます。

タグの互換性ルールの改善

編集
規格の文章(C23)

— improved tag compatibility rules, enabling more types to be compatible with other types;

解説
タグの互換性ルールに若干の変更が加わり、既存の矛盾を解消し、マクロを用いた汎用的なプログラミングを容易にし、代数的な型の構築を可能にすることができるようになりました。N2863 N2366 N2105

ビット精度の整数型 _BitInt の追加

編集
規格の文章(C23)

— added bit-precise integer types _BitInt( N) and unsigned _BitInt( N), where N can be an integer constant expression whose value is from one to BITINT_MAXWIDTH, inclusive.

解説
_BitIntは、ビット精度を指定するための型指定子です。指定されたビット数の整数型を表します。

以下に、_BitIntの使用例を示します。

#include <stdio.h>

int main() {
    _BitInt(8) byte;  // 8ビット整数型の変数byteを定義
    _BitInt(16) halfWord;  // 16ビット整数型の変数halfWordを定義
    _BitInt(32) word;  // 32ビット整数型の変数wordを定義

    byte = 255;  // byteに255を代入
    halfWord = 65535;  // halfWordに65535を代入
    word = 4294967295;  // wordに4294967295を代入

    printf("Byte: %d\n", byte);
    printf("Half Word: %d\n", halfWord);
    printf("Word: %d\n", word);

    return 0;
}

この例では、_BitIntを使用して8ビット、16ビット、32ビットの整数型を宣言し、それぞれの変数に値を代入しています。_BitIntを使用することで、特定のビット幅を持つ整数型を明示的に指定することができます。

この型の顕著な特性の1つは、性能上の理由から、デフォルトの整数プロモーションが行われないことです。 リテラル・サフィックス wb を使用することで、_BitInt とリテラルを含む式の不要な変換をさらに減らすことができます。N2960 N2946 N2775 N2709 N2646

enum の基礎となる型が指定可能に

編集
規格の文章(C23)

— improved rules for handling enumerations without underlying types, in particular allowing for enumerations without fixed underlying type to have value representations that have a greater range than int;

解説
列挙型に基礎となる型を指定する機能が追加されました。これによって、int よりも大きな範囲の値表現を持つことができるようになりました。
enum Colour : char {
  Red, 
  Green,
  Blue
};

XXX

規格の文章(C23)

— added a new colon-delimited type specifier for enumerations to specify a fixed underlying type (and which, subject to an implementation’s definitions governing such constructs, adopt the fixed underlying type’s rules for padding, alignment, and sizing within structures and unions as well as with bit-fields);

解説

stdbit.h

編集
規格の文章(C23)

— added a new header <stdbit.h> and a suite of bit and byte-handling utilities for portable access to many implementations’ most efficient functionality;

解説
ヘッダー <stdbit.h> が追加されました。

ビットおよびバイトを扱う一連のユーティリティを追加し、多くの実装の最も効率的な機能へポータブルにアクセスできるようにしました。

QCharやQVoidの導入

編集
規格の文章(C23)

— modified existing functions to preserve the const-ness of the type placed into the function;

解説
既存関数の宣言を変更し、関数内に配置された型の定数性( const-ness )を保持するようになりました。
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

編集
規格の文章(C23)

— added a feature to embed binary data as faithfully as possible with a new preprocessor directive

  1. embed;
解説
プリプロセッサディレクティブ #embed が追加された。

バイナリーデータを可能な限り忠実に埋め込む機能

nullptr定数とnullptr_t型を追加

編集
規格の文章(C23)

— added a nullptrP constant and a nullptr_t type with a well-defined underlying representation identical to a pointer to void`;

解説
nullptr定数とnullptr_t型が追加されました。voidへのポインタと同じように定義された基本表現を持ちます。N3042

__VA_OPT__

編集
規格の文章(C23)

— added the __VA_OPT__ specifier and clarified language in the handling of macro invocation and arguments;

解説
__VA_OPT__ は、マクロのパラメーターとして受け取った可変引数が空でない場合に置換するトークンを指定します。C++20

可変モディファイ型のサポートが義務化

編集
規格の文章(C23)

— mandated support for variably modified types (but not variable length arrays themselves);

解説
可変モディファイ型( Variably-Modified Types )のサポートを義務付けられました(ただし、可変長配列そのものではありません)。N2992
void foo(int n, double (*x)[n]) {
  (*x)[n] = 1; // 無効なアクセスは実行時に検出することができます
               // (場合によっては、より強力な解析によりコンパイル時にも検出可能) 
}

関数定義においてもパラメータ名が省略可能に

編集
規格の文章(C23)

— parameter names may be omitted in function definitions;

解説
関数の定義においてもパラメータ名を省略することができるようになりました。

関数の第一引数に ... が使用可能に

編集
規格の文章(C23)

— ellipses on functions may appear without a preceding parameter in the parameter list of functions and va_start no longer requires such an argument to be passed to it;

解説
関数定義の引数の省略記号( ... )は、関数のパラメーターリストにおいて先行するパラメータなしで現れることができるようになりました。va_startはもはやそのような引数が渡されることを必要としません。

Unicode 識別子更新

編集
規格の文章(C23)

— Unicode identifiers allowed in syntax following Unicode Standard Annex, UAX #31;

解説
Unicode 識別子が、UAX(Unicode Standard Annex) #31 に従うようになりました。

memset_explicit関数の追加

編集
規格の文章(C23)

— added the memset_explicit function for making sensitive information inaccessible;

解説
C23にmemset_explicit関数の目的は、メモリ上の機密データ(パスワードやキーデータなど)を確実に消去することです。通常のmemset関数は最適化によって呼び出しが削除される可能性がありますが、memset_explicitは常に実行されることが保証されます。
  • C++にも同様の std::memset_explicit 関数テンプレートを追加する提案がある。
背景には、機密データを適切に消去する可搬で標準的な方法がC/C++にないという問題があります。開発者は様々な回避策を講じていますが、完全な解決にはなっていません。C11のmemset_s関数は同様の目的を持つものの、Annex K(オプション)であり広く実装されていないため、実用的ではありませんでした。

memalignment関数の追加

編集
規格の文章(C23)

— added memalignment function to query the alignment of a pointer;

解説
memalignment 関数は、ポインタを引数に取り、そのポインタが満たすアライメントを size_t 型で返します。N2852
  • C言語には、ポインタがある型のアライメント要件を満たすかどうかを確認する方法がありません。ポインタ(通常は void*) から他の型へキャストする際に、少なくとも1つの未検証の仮定が必要になります。
  • 浮動小数点数型や _Atomic 型などには、厳格なアライメント要件があります。他の型にも、パフォーマンス上の理由からアライメントを期待する場合があります。
  • ポインタのアライメントを確認できれば、安全にキャストできるかどうかを判断できます。
memalignment 関数の動作は以下の通りです:
  • void* ポインタを引数に取り、そのポインタが満たすアライメントの最大値を size_t 型で返します。
  • 返された値は、 _Alignof から得られる型のアライメント要件と比較できます。返された値が型のアライメントより大きいか等しい場合、そのポインタは型のオブジェクトを指せます。
memalignment 関数は <stddef.h> ヘッダーに追加され、フリースタンディング環境でも利用可能となる予定です。

幅を明記した整数型

編集
規格の文章(C23)

— certain type definitions (i.e. exact-width integer types such as int128_t), bit-precise integer types, and extended integer types may exceed the normal boundaries of intmax_t and uintmax_t for signed and unsigned integer types, respectively;

解説
C言語には、整数型として符号付き整数と符号なし整数が定義されています。従来これらの整数型のビット幅や値の範囲には制限がありました。例えば、32ビットマシンでは int 型は通常32ビットつまり4バイトで、最大値は2^31-1、最小値は-2^31です。
しかし、近年のハードウェアの進化に伴い、従来の整数型の範囲では不足する場面も出てきました。そこでC23では、以下の3種類の新しい整数型が導入されることになりました。
exact-width 整数型

︰:ビット幅が厳密に規定された整数型です。代表例として `int128_t` があり、これは128ビットの整数型です。符号付きでも符号なしでも定義可能です。

bit-precise 整数型
パディングビットを許可しない整数型です。つまり、メモリ上のビット列とデータ表現が完全に一致します。ビット操作が必要な低レベル開発などに有用です。
extended 整数型
従来の符号付き最大整数型 `intmax_t` や符号なし最大整数型 `uintmax_t` よりも、さらに大きな値の範囲を持つ整数型です。
これらの新しい整数型が加わることで、プログラマーは用途に応じてビット幅や値の範囲を自在に選べるようになります。一方で、扱う値の範囲が非常に大きくなる可能性もあり、演算やライブラリ関数の拡張が必要になるかもしれません。

潜在的に予約された識別子

編集
規格の文章(C23)

— names of functions, macros, and variables in this document, where clarified, are potentially reserved rather than reserved to avoid undefined behavior for a large class of identifiers used by programs existing and to be created;

解説
既存および新規のプログラムで使われている識別子が、将来の言語拡張で予約される可能性を排除するために、新しい「潜在的に予約された(potentially reserved)」という概念を導入しました。

call_once

編集
規格の文章(C23)

— mandated support for call_once;

解説
C23における主な変更点は以下の通りです。
  • call_once関数が必須機能になる
  • スレッドの有無に関わらず、call_once関数が利用可能になる
  • <stdlib.h>ヘッダーに、once_flag型とONCE_FLAG_INITマクロが追加される
これにより、マルチスレッド環境だけでなく、単一スレッド環境においても、一度だけ実行される初期化ルーチンを簡単に記述できるようになります。動的な初期化処理のニーズに幅広く対応できるようになるという点が、最大の変更点です。
実装の影響は最小限で、スレッドが存在する環境ではatomicを使った実装、スレッドがない環境では静的変数のポーリングなどで比較的容易に実装可能です。

ptrdiff_t型の値の範囲

編集
規格の文章(C23)

— allowed ptrdiff_t to be an integer type with a width of at least 16, rather than requiring an integer type with a width of at least 17;

解説
C23では、ptrdiff_t型の値の範囲について、従来の「少なくとも17ビット幅の整数型」から「少なくとも16ビット幅の整数型」に緩和されました。
この変更は、16ビットマシンでのポータビリティを維持しつつ、32/64ビットマシンでの広い実装も許容するためのものです。下位互換性と上位互換性の両立を図った変更と言えます。

__has_include機能

編集
規格の文章(C23)

— added the __has_include feature for conditional inclusion expression preprocessor directives to check if a header is available for inclusion;

解説
__has_includeは、C23で導入されたプリプロセッサディレクティブであり、プログラム中で特定のヘッダファイルが存在するかどうかを確認するために使用されます。この機能により、異なる環境で異なるヘッダファイルを条件付きでインクルードすることが容易になります。
  • 機能名: __has_include
  • 役割: ヘッダファイルの存在確認
  • 使用方法: #if __has_include(<ヘッダファイル>)または#if __has_include("ヘッダファイル")

_Imaginary_I と _Complex_I マクロの型修飾子 const を削除

編集
規格の文章(C23)

— changed the type qualifiers of the _Imaginary_I and _Complex_I macros;

解説
_Imaginary_I と _Complex_I マクロは型修飾子 const を伴うとされていましたが、合理的な理由がなくC++とも調和しないので削除されました。
規格の文章(C23)

— added qualifier preserving macros for bsearch, memchr, strchr, strpbrk, strrchr, strstr, wcschr, wcspbrk, wcsrchr, wmemchr, and wcsstr;

解説
規格の文章(C23)

— added (U+0040, COMMERCIAL AT), $ (U+0024, DOLLAR SIGN), and ` (U+0060, GRAVE ACCENT, "Backtick") into the source and execution character set;

解説

型推論

編集
規格の文章(C23)

— enhanced the auto type specifier for single object definitions using type inference;

解説

型推論( 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 fname = "/etc/hosts";
    auto file = fopen(fname, "r");

    if (file == NULL) {
        perror(fname);
        return 1;
    }

    // ファイルから1行ずつ読み込んで標準出力に表示
    char line[256];
    for (auto i = 1; fgets(line, sizeof(line), file); i++) {
        printf("%03d: %s", i, line);
    }

    fclose(file);
    return 0;
}

この例の

    auto fname = "/etc/hosts";
    auto file = fopen(fname, "r");
      ...
    for (auto i = 1; fgets(line, sizeof(line), file); i++) {

は、これまでならば

    const char *fname = "/etc/hosts";
    FILE *file = fopen(fname, "r");
      ...
    for (int i = 1; fgets(line, sizeof(line), file); i++) {

と書くところですが、型推論を使い型名を明示しないで済んでいます。

規格の文章(C23)

— added the #elifdef and #elifndef conditional inclusion preprocessor directives;

解説
規格の文章(C23)

— added the #warning preprocessing directive;

解説
規格の文章(C23)

— binary integer literals and appropriate formatting for input/output of binary integer numbers;

解説
規格の文章(C23)

— digit separators with ’ (single quotation mark);

解説
規格の文章(C23)

— removed conditional support for mixed wide and narrow string literal concatenation;

解説
規格の文章(C23)

— added support for additional time bases, as well as timespec_getres, in <time.h>;

解説
規格の文章(C23)

— added support for new interface timegm to retrieve the broken-down time, in <time.h>;

解説
規格の文章(C23)

— zero-sized reallocations with realloc are undefined behavior;

解説
規格の文章(C23)

— added free_sized and free_aligned_sized functions;

解説
規格の文章(C23)

— added an unreachable feature which has undefined behavior if reached during program execution;

解説
規格の文章(C23)

— added printf and scanf length modifiers for intN_t, int_fastN_t, uintN_t, and uint_fastN_t.

解説

N3096 の冒頭から

編集
規格の文章(C23)

The following documents, for all intents and purposes, have been applied to this draft from before and during the October 2019 Meeting:

トリグラフの削除

編集
規格の文章(C23)

N2940 Remove Trigraphs??!

解説
#??= の3文字で表すトリグラフ(JIS語では「3文字表記」)が規格から削除されました。C++では既にC++17で削除されています。

符号付き整数の形式は二の補数に限定

編集
規格の文章(C23)

N2412 Two’s complement sign representation for C2x

解説
「C言語から2の補数以外の符号表現を削除することで、整数型の仕様を大幅に簡素化することができる」とし「他の符号表現の仕様」を排除しました。

二進数リテラル

編集
規格の文章(C23)

N2549 Binary Literals

解説
二進数リテラルが追加されました。二進数リテラルは、接頭辞0bまたは0Bの後に0または1の数字が連続したものです。C++では既にC++14で二進数リテラルが導入されています。


二進整数の書式付き入出力

編集
規格の文章(C23)

N2612 Formatted input/output of binary integer numbers

解説
二進数リテラルに呼応する形でprintf系とscanf系の関数に書式 %b が追加されました。

脚註

編集
  1. ^ N3054によると、__STDC_VERSION__ は 202311L となるようです。
  2. ^ C23 now finalized!

外部リンク

編集