web-dev-qa-db-ja.com

char配列宣言の文字列リテラルを中括弧で囲んでください。 (例:char s [] = {"Hello World"})

偶然、行char s[] = {"Hello World"};が適切にコンパイルされており、char s[] = "Hello World";と同じように扱われているように見えることがわかりました。最初の({"Hello World"})は、charの配列である1つの要素を含む配列ではないので、sの宣言はchar *s[]と読む必要がありますか?実際、これをchar *s[] = {"Hello World"};に変更すると、期待どおり、コンパイラーもそれを受け入れます。

答えを探して、これに言及した唯一の場所は これ ですが、標準の引用はありません。

だから私の質問は、左側がchar s[] = {"Hello World"};型で、右側がarray of char型であるのに、なぜ行array of array of charがコンパイルされるのかということです。

以下は実用的なプログラムです。

#include<stdio.h>
int main() {
    char s[] = {"Hello World"};
    printf("%s", s); // Same output if line above is char s[] = "Hello World";
    return 0;
}

ご不明な点がございましたら、ありがとうございます。

P.S.私のコンパイラはgcc-4.3.4です。

50
halex

標準がそう言っているのでそれは許可されます:C99セクション6.7.8、§14:

文字タイプの配列は、オプションで中括弧で囲まれた文字列リテラルによって初期化できます。文字列リテラルの連続する文字(スペースがある場合、または配列のサイズが不明な場合の終了ヌル文字を含む)は、配列の要素を初期化します。

これが意味するのは、両方

char s[] = { "Hello World" };

そして

char s[] = "Hello World";

糖衣構文にすぎません

char s[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 };

関連する注記(同じセクション、§11)で、Cは次のようなスカラー初期化子を中括弧で囲むこともできます。

int foo = { 42 };

ちなみに、これは複合リテラルの構文にうまく適合します

(int){ 42 }
64
Christoph

中括弧はオプションであり、式は文字の配列と同等です。

これを書くこともできます:

 int a = {100}; //ok

デモ: http://ideone.com/z0psd

実際には、 C++11は、この構文そのものを一般化して、非配列と配列を均一に初期化します。だからC++11、あなたはこれらを持つことができます:

int a{}; //a is initialized to zero, and it is NOT an array

int b[]{1,2,3,4}; //b is an array of size 4 containing elements 1,2,3,4

int c[10]{}; //all 10 elements are initialized to zero

int *d{}; //pointer initialized to nullptr

std::vector<int> v{1,2,3,4,5}; //vector is initialized uniformly as well.
22
Nawaz

intcharなど)の変数は、長さ1の配列にすぎません。

char s = {0};

同様に動作します。

3
Dennis

私は間違っているかもしれませんが、これは文字の配列の配列ではないと思いますが、ブロックには文字の配列が含まれています。 int a = {1};も同様に機能する可能性があります。

2
MByD

これは、C++標準でも許可されています。引用:

[dcl.init.string]§1

ナロー文字型([basic.fundamental])、char16_t配列、char32_t配列、またはwchar_t配列の配列は、それぞれナロー文字列リテラル、char16_t文字列リテラル、char32_t文字列リテラル、またはワイド文字列リテラルで初期化できますまたは適切に型指定された文字列リテラルを中括弧で囲みます([Lex.string] )。 [をちょきちょきと切る]

1
eerorika

[...]実際、char * s [] = {"HelloWorld"}に変更すると;コンパイラは期待どおりにそれも受け入れます

コンパイラはそれを受け入れます。なぜなら、実際には、1つの要素のみを格納した未定義のサイズの要素の2D配列を作成しているからです。"Hello World" ストリング。このようなもの:

char* s[] = {"Hello world", "foo", "baa" ...};

この場合、bracetsを省略することはできません。

1
Jack