2017-03-20 1 views
4

次はgccバージョン6.3で有効なcコードとして受け入れられていますこれが合理的な理由であるとはいえ、私はそれが何であるか不思議です。この質問は、"\x43\xde\xa0"ではなく{ '\x43', '\xde', '\xa0' }のようなものを書き込むことが非常に魅力的で、*my_arrayの代わりにmy_array[]を書くのを忘れるとすぐに、バイト配列(unsigned charではなくcharではなく)を初期化する必要がある場合の動機になります。コンパイラに捕まってしまう。C char型の配列vのCのchar *を初期化

+5

文字列の末尾にヌルターミネータ( '\ 0')がないため、' white'の定義は他の2つの文字列と同じではありません。 – abelenky

+0

@abelenkyああ、これは私が見落とした良い点です、ありがとうございます。 –

+0

'char * green = {" a "、" b "、" c "};' ....;) – LPs

答えて

7

あなたが信じているよう​​の初期化子は、文字の配列されていないため、次のエラー

char *green = { 'a', 'b', 'c' }; 

を生成します。それは型を持たない、それは単に中括弧で囲まれたイニシャライザリストです。以前のサンプル(つまりwhite)で初期化されたものが、その解釈方法を決定します。同じ文字列を使用して、3文字を保持できる集約を初期化することができます。

しかし、​​は、ポインタであり、集約ではないため、初期値として中括弧で囲まれた初期化リストを使用することはできません。

は、次の2つの作業が、非常に異なる意味を持つ:

char blue[] = "abc"; 
char *red = "abc"; 

blue配列です。リテラル​​と同じ内容を保持します。 redのポインターで、の文字は​​です。


  1. あなたがcompound literal expression使用することができます。

    char *green = (char[]){ 'a', 'b', 'c' }; 
    

    それは無名のオブジェクトを作成するために、コンパイラに指示します(宣言のスコープに依存するの寿命を)、それはですこれらの3文字で初期化されます。ポインタにはそのオブジェクトのアドレスが割り当てられます。

+0

すべてが本当です。しかし、イニシャライザのリストを 'char'配列のリテラル(文字列リテラルではなく)に変更し、' char * '宣言の意味を議論することで、' char *そうする。 –

+0

@JohnBollinger - 私は複合リテラルについての情報を入力していました。 – StoryTeller

+0

@StoryTeller大変ありがとうございます。 –

5

これらの三つの宣言

char white[] = { 'a', 'b', 'c' }; 
char blue[] = "abc"; 
char *red = "abc"; 

は異なっています。

最初の文字は、イニシャライザの数に対応する3文字の文字配列を宣言します。

2番目の文字配列は、終了ゼロを含む4文字の文字列リテラルによって初期化されるため、4文字の文字配列を宣言します。したがって、この文字配列には文字列が含まれています。

文字配列である文字列リテラルを定義し、文字列リテラルに対応する文字配列の最初の文字のアドレスによって初期化されるタイプchar *のポインタを宣言します。

あなたは左のオブジェクトがスカラーで、複数の初期化子を含むリストによって初期化されていない可能性があるため、この宣言

char *green = { 'a', 'b', 'c' }; 

が無効である

char unnamed = { 'a', 'b', 'c', '\0' }; 
char *red = unnamed; 

のように、この宣言を想像することができます。

複合リテラルを使用してポインタを初期化できることを考慮してください。たとえば、

char *green = (char[]){ 'a', 'b', 'c' }; 
+0

ありがとうございました –

+0

@SvenWilliamson全くありません。どういたしまして。 –