リテラルについても、C++(C++11以降)とC11では微妙なちがいがあります

文字定数

C++では「文字リテラル」といいますが、C11では「文字定数」という用語が使われています。

C++の文字リテラルはchar型でしたが、C11の文字定数はint型です。C11では多重定義(オーバーロード)がありませんので、sizeof演算子のオペランドに文字定数を指定しないかぎり、この違いが問題になることはとくにないでしょう。

C11でも、ワイド文字定数はwchar_t型です。しかし、wchar_t型自体が基本型ではなく、実体は一般の整数型ですので、その意味ではC++とは異なります。しかし、これも具体的に問題になることはまずないでしょう。char16_t型やchar32_t型も一般の整数型ですので、それぞれの型の文字定数も普通の整数型になります。なお、C11ではu8を付けた文字定数は使えません。

文字列リテラル

C++の文字列リテラルはconst char型の配列でしたが、C11の文字列リテラルはchar型の配列です。しかし、文字列リテラルの各要素に書き込んだ場合の動作は未定義です。C11でもC++同様、生文字列リテラルを使用することができます。

文字列リテラルによる配列の初期化

文字列リテラルを使った配列の初期化では、C++とC11では微妙な違いがあります。C++では、3要素しかない配列を3文字の文字列リテラルで初期化しようとするとエラーになりました。しかし、C11では、終端のナル文字が格納されることなく、コンパイルできてしまいます。

上記のコードは、{ ‘a’, ‘b’, ‘c’ }を初期化子にした場合と同じ結果になります。

整数定数

C++では「整数リテラル」といいますが、C11では「整数定数」という用語が使われています。

真理値定数

C++には、trueおよびfalseという真理値リテラルがありました。C11には真理値を表す_Bool型がありますが、真理値を表す特別な定数はなく、整数定数である1と0を使います。<stdbool.h>ヘッダではtrueおよびfalseマクロが定義されますが、これらは単なる整数定数である 1 および0に展開されます。

複合リテラル

C++のクラスはコンストラクタを定義することができますが、C言語の構造体や共用体ではコンストラクタを定義することができません。そのため、通常であれば、いったん初期化子を指定したオブジェクトを定義し、それを使うしかありません。ところが、そうした方法では、文を使える文脈であればよいのですが、式しか使えないような文脈では簡潔な書き方ができなくなります。

C11では、構造体・共用体・配列に関して、「複合リテラル」という一種のリテラルを使うことがでいます。具体的には次のように書きます。

C++では、配列にコンストラクタは定義できませんし、vectorなどのコンテナでも要素を一つ一つ指定したコンストラクタの呼び出しはできません。それに対して、C11では、配列に関しても同様に複合リテラルが使えますので、かなり強力になっています。

もちろん、構造体型の配列や多次元配列など、複雑な型であっても複合リテラルを使うことができます。また、複合リテラルに要素指示子を使うこともできます。


↑ モダンC++プログラマーのためのC11入門