21

C コードを C++ に移行しています。
次のコードが C で適切に定義されていることに気付きました。

int main(){

  //length is valid. '\0' is ignored
  char  str[3]="abc";
}

配列の初期化で次のように述べられています。

「配列のサイズがわかっている場合、文字列リテラルのサイズよりも 1 小さい可能性があります。この場合、終端の null 文字は無視されます。」

ただし、C++ で同じコードをビルドすると、次の C++ エラーが発生します。

error: initializer-string for array of chars is too long
[-fpermissive]    char  str[3]="abc";

誰かがこれについて説明できることを願っています。

質問:
コード例はすべての C 言語標準で有効ですか?
すべての C++ 言語標準で無効ですか?
ある言語では有効で、別の言語では有効でない理由はありますか?

4

2 に答える 2

17

ここでわかるのは、C と C++ での cstring の初期化規則の違いです。C11 §6.7.9/14 では、

文字型の配列は、文字列リテラルまたは UTF-8 文字列リテラルで初期化することができ、オプションで中括弧で囲みます。文字列リテラルの連続するバイト (空きがある場合、または配列のサイズが不明な場合は、終端の null 文字を含む) は、配列の要素を初期化します。

強調鉱山

そのため、配列が null ターミネータを除く文字列に対して十分な大きさである限り、配列は有効です。そう

char  str[3]="abc";

有効な C です。ただし、C++14 では、[dcl.init.string]/2 にあるこれを管理するルールは次のように述べています。

配列要素よりも多くの初期化子があってはなりません。

さらに、次のコードがエラーであることを示します

char cv[4] = "asdf"; // error

したがって、C++ では、ヌル ターミネータを含む文字列リテラル全体に十分なストレージが必要です。

于 2016-06-16T14:25:53.317 に答える