web-dev-qa-db-ja.com

構造体の配列の初期化

他の誰かの質問で見つけた初期化は次のとおりです。

my_data data[]={
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

私はこれまでこのようなものを見たことがなく、.nameが正しい可能性があるという説明を見つけることができません。
私が探しているのは、このプロセスが段階的に進む方法です。

次のように見えます:

1) data;
2) *data;
3) (*data).name;
4) (*data).name="Peter";

それとも私は完全に間違っていますか?

21
zubergu

ここでは、2つの構文のみが使用されています。

  1. 単純な古い配列の初期化:

    int x[] = {0, 0}; // x[0] = 0, x[1] = 0
    
  2. 指定されたイニシャライザー。この質問に対する受け入れられた答えを参照してください: Cプログラミング言語標準に従って構造体を初期化する方法

    ただし、構文はかなり自明です。次のように初期化できます。

    struct X {
        int a;
        int b;
    }
    struct X foo = { 0, 1 }; // a = 0, b = 1
    

    または任意の順序を使用するには、

    struct X foo = { .b = 0, .a = 1 }; // a = 1, b = 0
    
21
Dave

my_datanameをフィールドとして持つ構造体であり、data[]は構造体の一部です。各インデックスを初期化しています。以下をお読みください:

5.20指定イニシャライザー

構造イニシャライザーで、エレメント値の前に.fieldname ='で初期化するフィールドの名前を指定します。たとえば、次の構造を考えると、

 struct point { int x, y; };

次の初期化

 struct point p = { .y = yvalue, .x = xvalue };

に等しい

 struct point p = { xvalue, yvalue };

GCC 2.5で廃止された同じ意味を持つ別の構文は、次のようにfieldname:'です。

 struct point p = { y: yvalue, x: xvalue };

以下を書くこともできます。

my_data data[]={
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

なので:

my_data data[]={
    { [0].name = "Peter" },
    { [1].name = "James" },
    { [2].name = "John" },
    { [3].name = "Mike" }
}; 

上の例のように書く必要がないので、2番目の形式は便利かもしれません:

my_data data[]={
    { [3].name = "Mike" },
    { [1].name = "James" },
    { [0].name = "Peter" },
    { [2].name = "John" }
}; 

配列の初期化を理解するには、 Strange initializer expression?
また、スイッチケースに対する@ Shaf​​ik Yaghmour の回答も読むことができます: Cコードのスイッチケースの「…」とは何ですか

22
Grijesh Chauhan

ここには「ステップバイステップ」はありません。定数式を使用して初期化が実行される場合、プロセスは基本的にコンパイル時に実行されます。もちろん、配列がローカルオブジェクトとして宣言されている場合、ローカルに割り当てられ、実行時に初期化されますが、それでも意味のある細分化ができないシングルステッププロセスと考えることができます。

指定された初期化子を使用すると、構造体オブジェクトの特定のメンバー(または配列の特定の要素)に初期化子を提供できます。他のすべてのメンバーはゼロで初期化されます。したがって、my_dataは次のように宣言されます

typedef struct my_data {
  int a;
  const char *name;
  double x;
} my_data;

あなたの

my_data data[]={
    { .name = "Peter" },
    { .name = "James" },
    { .name = "John" },
    { .name = "Mike" }
};

単によりコンパクトな形式です

my_data data[4]={
    { 0, "Peter", 0 },
    { 0, "James", 0 },
    { 0, "John", 0 },
    { 0, "Mike", 0 }
};

後者が何をするのか知っていることを願っています。

15
AnT

これは指定されたイニシャライザと呼ばれ、C99で導入されました。 structまたは配列(この例ではstruct)を初期化するために使用されます。

与えられた

struct point { 
    int x, y;
};

次の初期化

struct point p = { .y = 2, .x = 1 };

c89スタイルと同等です

struct point p = { 1, 2 };
2
Yu Hao

これは非常に簡単です。my_dataは、事前に定義された構造タイプです。したがって、いくつかの要素のmy_data- arrayを宣言する必要があります。

char a[] = { 'a', 'b', 'c', 'd' };

したがって、配列には4つの要素があり、それらを次のように初期化します。

a[0] = 'a', a[1] = 'b', a[1] = 'c', a[1] ='d';

これは、指定されたイニシャライザーと呼ばれます(覚えているとおりです)。

また、データはmy_dat型である必要があり、Peter、James、John、Mikeの各型メンバー名を持つ構造があるほど多くのmy_data構造を格納する必要がある配列でなければならないことを示しています。

1
dhein

これは、C99標準で導入された指定されたイニシャライザです。 structまたはunionオブジェクトの特定のメンバーを名前で初期化できます。 my_dataは、明らかにchar *またはchar [N]型のメンバーstructを持つname型のtypedefです。

0
John Bode