web-dev-qa-db-ja.com

C構造体の部分的な初期化

この link は、「自動配列または自動構造に部分的な初期化子がある場合、残りは0に初期化される」と述べています。次のコードを読んで書いたことを試してみることにしました。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    //int arr[3] = {2};  // line no. 7

    struct s {
        int si;
        int sj;
    };

    struct s myStruct;
    myStruct.si = 9;
    printf("%d\n", myStruct.sj);
}

4096をコメントアウトするとline no. 7(「ガベージ」値だと思われる)が表示され、0のコメントを外すとline no. 7が表示される理由がわかりません。 arr宣言がmain()のアクティベーションレコード(またはmyStruct)に関係しているとは思わない(コメントされていないline no. 7がある場合):

---------------
|  Saved PC   |
---------------
|  arr[2]     |
---------------
|  arr[1]     |
---------------
|  arr[0]     |
---------------
|  si         |
---------------
|  sj         |
---------------

誰かがここで私が見逃していることを説明してもらえますか?

27
babon

これを行うとき:

struct s myStruct;
myStruct.si = 9;

あなたはinitializingmyStructではありません。初期化子なしで宣言してから、ステートメントを実行して1つのフィールドを設定します。

変数は初期化されていないため、その内容は未定義であり、変数の読み取りは 未定義の動作 です。これは、一見無関係な変更がこの動作を変更する可能性があることを意味します。この例では、myStruct.sjが0になるように追加の変数happenedを追加していますが、これが当てはまるという保証はありません。

変数をinitializeするには、definedになった時点で値を指定する必要があります。

struct s myStuct = { 9 };

これを行うと、myStruct.sjの内容が0に設定されます。これは、 C標準 のセクション6.7.8に従って保証されます(この場合に特有の強調表示付き) :

10自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不定です。 静的な保存期間を持つオブジェクトが明示的に初期化されていない場合、次のようになります:

-ポインタータイプがある場合、nullポインターに初期化されます。

算術型の場合、(正または符号なし)ゼロに初期化されます;

それが集合体である場合、すべてのメンバーはこれらのルールに従って(再帰的に)初期化されます;

-ユニオンの場合、最初の名前付きメンバーはこれらの規則に従って(再帰的に)初期化されます。

...

21括弧で囲まれたリストの初期化子が、集合体の要素またはメンバーよりも少ない場合、または初期化に使用される文字列リテラルの文字数が少ない場合配列内の要素があるよりも既知のサイズの配列、集合体の残りの部分は、静的ストレージ期間を持つオブジェクトと同じように暗黙的に初期化されます。

51
dbush

あなたの場合、

 myStruct.si = 9;

代入ステートメント、not初期化。この場合、構造変数(および対応する変数)は初期化されていません。したがって、初期化されていない変数sjの値を読み取ってしまい、 未定義の動作 になります。

あなたが試すことができます

struct s myStruct = {9};

動作中の暗黙的な初期化を確認します。

15
Sourav Ghosh

これは初期化子ではありません。構造は初期化されていないので、siのみを割り当てます。 sjは初期化されません。

この本はこの種のコードに言及しています:

struct s myStruct = {9};

...ここで、sjは0であることが保証されています。

11
Quentin

これは基本的に、他の人がすでに与えた素晴らしい答えの、多かれ少なかれ完全な例です。

#include<stdio.h>

struct{
  int a;
  int b;
}obj1={.a=0}; //Partial initialization

typedef struct struct_B{
  int a;
  int b;
}struct_B;

int main(void)
{
  printf("obj1.b : %d\n",obj1.b);
  struct_B obj2={.b=1,.a=0,0}; // b's first value is overridden here as 0 immediately follows a
  printf("obj2.b : %d\n",obj2.b);
  struct_B obj3={0}; //Partial initialization, here the '0' value is meant for a as it comes first in the declaration
  printf("obj3.b : %d\n",obj3.b);
  struct_B obj4={.a=0}; //Partial initialization
  printf("obj4.b : %d\n",obj4.b);
  return 0;
}

出力:

obj1.b : 0
obj2.b : 0
obj3.b : 0
obj4.b : 0
2
sjsam