web-dev-qa-db-ja.com

Cプログラミング言語の標準に従って構造体を初期化する方法

宣言と初期化に分けて、struct要素を初期化したいのですが。これは私が持っているものです:

typedef struct MY_TYPE {
  bool flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

これは、Cプログラミング言語の標準(C89、C90、C99、C11など)に従ってMY_TYPEのローカル変数を宣言および初期化する方法ですか?それとももっと良い、あるいは少なくともうまくいくものはありますか?

更新 私は自分のニーズに応じてすべてのサブ要素を設定する静的な初期化要素を持つことになりました。

409
cringe

(ANSI)C99では、 指定イニシャライザ を使って構造を初期化することができます。

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

編集:他のメンバはゼロとして初期化されます。 ( https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

665
philant

複合リテラル でそれを実行できます。そのページによると、C99で動作します(これは ANSI C としてもカウントされます)。

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

イニシャライザの指定はオプションです。あなたはまた書くことができます:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
177
CesarB

私はあなたがすでにANSI C 99についての答えを受け取っているのを見たので、私はANSI C 89についての骨を投げるつもりです。ANSI C 89はあなたがこのように構造体を初期化することを可能にします:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

覚えておくべき重要なことは、構造体内の1つのオブジェクト/変数を初期化した瞬間に、他のすべての変数はデフォルト値に初期化されるということです。

構造体の値を初期化しないと、すべての変数に「ガベージ値」が含まれます。

がんばろう!

84
Ron Nuni

a = (MYTYPE){ true, 15, 0.123 };

c99でうまくいくでしょう

35
qrdl

あなたはほとんどそれを持っています...

MY_TYPE a = { true,15,0.123 };

クイック 'struct initialize c'で検索これを見せてくれ

18
Kieveli

ロンヌニが言ったように:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

覚えておくべき重要なこと:構造体の中の1つのオブジェクト/変数でさえ初期化すると、他のすべての変数はデフォルト値に初期化されます。

あなたがあなたの構造体の中で値を初期化しないならば(すなわち、あなたがその変数を宣言するだけなら)、すべてのvariable.membersは "ガベージ値"を含みます、 宣言がローカルである場合だけ!

宣言が globalまたはstatic の場合(この場合のように)、すべての未初期化variable.membersは自動的に次のように初期化されます。

  • 整数と浮動小数点数の場合は0
  • char'\0'(もちろんこれは0と同じであり、charは整数型です)
  • ポインタの場合はNULL
13
r_goyal

Cプログラミング言語規格 ISO/IEC 9899:1999 (一般にC99として知られている)は、 指定イニシャライザ を使用して、次のように構造体または共用体のメンバを初期化できます。

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

これは、ISO/IEC 9899:1999規格のparagraph 7、セクション6.7.8 Initializationで次のように定義されています。

指定子が次の形式をとる場合
識別子
そして、現在のオブジェクト(以下に定義)は構造体型または共用体型を持ち、識別子はその型のメンバーの名前になります。

同じセクションのparagraph 9には、次のように記載されています。

他に明示的に述べられている場合を除き、この副次句の目的のために、構造体および共用体型のオブジェクトの無名メンバーは、初期設定に参加しません。 構造化オブジェクトの無名メンバーは、初期化後も値が不定です。

ただし、GNU GCCの実装では、省略されたメンバーはゼロまたはゼロのような型に適した値として初期化されます。 GNU GCCのドキュメントの 6.27指定イニシャライザ に記載されているように、

省略されたフィールドメンバは、静的記憶期間を持つオブジェクトと同じように暗黙的に初期化されます。

公式のブログ投稿 C++ Conformance Roadmap によると、Microsoft Visual C++コンパイラはバージョン2013以降の指定イニシャライザをサポートするべきです。 MSDN Visual Studioのドキュメントの Initializers の段落Initializing unions and structsは、GNU GCCと同様に、名前のないメンバを0のような適切な値に初期化することを提案しています。

ISO/IEC 9899:2011 standard(一般にC11として知られている)は、ISO/IEC 9899:1999に取って代わって、指定された初期化子を6.7.9 Initializationセクションの下に保持します。 paragraph 9も変更されていません。

新しい ISO/IEC 9899:2018 standard(一般にC18として知られている)は、ISO/IEC 9899:2011に取って代わり、指定された初期化子を6.7.9 Initializationセクションの下に保持します。 paragraph 9も変更されていません。

13
PF4Public
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
4
robert

構造体を初期化する別の方法を見つけました。

構造体:

typedef struct test {
    int num;
    char* str;
} test;

初期化:

test tt = {
    num: 42,
    str: "Nice"
};

GCCのドキュメントによると、この構文は GCC 2.5から廃止されました

2
MichaelWang

MSがC99に更新されていない場合、MY_TYPE a = {true、15,0.123}。

2
eddyq

私はこれらの答えのどれも好きではなかったので私は私自身のものを作りました。これがANSI Cであるかどうかはわかりません。デフォルトモードではGCC 4.2.1です。括弧を覚えることは決してできないので、私は自分のデータのサブセットから始め、それが終了するまでコンパイラのエラーメッセージと戦います。読みやすさが私の最優先事項です。

    // in a header:
    typedef unsigned char uchar;

    struct fields {
      uchar num;
      uchar lbl[35];
    };

    // in an actual c file (I have 2 in this case)
    struct fields labels[] = {
      {0,"Package"},
      {1,"Version"},
      {2,"Apport"},
      {3,"Architecture"},
      {4,"Bugs"},
      {5,"Description-md5"},
      {6,"Essential"},
      {7,"Filename"},
      {8,"Ghc-Package"},
      {9,"Gstreamer-Version"},
      {10,"Homepage"},
      {11,"Installed-Size"},
      {12,"MD5sum"},
      {13,"Maintainer"},
      {14,"Modaliases"},
      {15,"Multi-Arch"},
      {16,"Npp-Description"},
      {17,"Npp-File"},
      {18,"Npp-Name"},
      {19,"Origin"}
    };

データはタブ区切りのファイルとして始まることがあり、それを他のものに変換するために検索置換します。はい、これはDebianのものです。そのため、{}の外側の1つのペア(配列を示す)、次に各内部構造体の別のペア。間にカンマを入れます。ヘッダに物を入れることは厳密には必要ではありませんが、私は自分の構造体の中に50個の項目を持っているので、それらを別々のファイルに入れておきます。

1
Alan Corey

Microsoft Visual Studio 2015の集計タイプの初期化に関するドキュメントを読んだことがあります / {...}を使った初期化のすべての形式はここで説明されていますが、「 'designator'」という名前のドットを使った初期化は説明されていません。また動作しません。

C99標準の6.7.8章初期化は指示子の可能性を説明していますが、私の考えでは複雑な構造体についてはそれは明確ではありません。 pdfとしての C99規格

私の考えでは、

  1. すべての静的データに= {0};-初期化を使用してください。機械語コードの手間が省けます。
  2. たとえば、初期化にマクロを使用する

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

マクロを適合させることができ、その引数リストは変更された構造体の内容とは無関係にすることができます。より少ない要素を初期化する必要がある場合は適切です。入れ子になった構造体にも適しています。 3.簡単な形式は次のとおりです。サブルーチンで初期化します。

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

このルーチンは、CのObjectOrientedに似ています。C++でもコンパイルするには、thizではなくthisを使用してください。

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);
0

Cの構造体は、次のように宣言して初期化できます。

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}
0
Ajay Parashar