Cの構造体メンバーのデフォルト値


82

一部の構造体メンバーにデフォルト値を設定することは可能ですか?次のことを試しましたが、構文エラーが発生します。

typedef struct
{
  int flag = 3;
} MyStruct;

エラー:

$ gcc -o testIt test.c 
test.c:7: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
test.c: In function ‘main’:
test.c:17: error: ‘struct <anonymous>’ has no member named ‘flag’

構造体の初期化関数を作成できます。
sgarizvi 2012

4
Cにはありません。ただし、必要な値を持つ構造体を返す関数を作成できます。
Vaughn Cato 2012

あなたがそれを作成するとき、あなたはこのように値を初期化することができます: stackoverflow.com/questions/749180/default-values-in-ac-struct
Fantastic Mr Fox

C ++構造体の場合、コンストラクターでデフォルトデータを初期化できます
Zac

回答:


122

構造はデータ型です。データ型に値を指定しません。データ型のインスタンス/オブジェクトに値を指定します。
したがって、これはCでは不可能です。

代わりに、構造体インスタンスの初期化を行う関数を作成できます。

または、次のようにすることもできます。

struct MyStruct_s 
{
    int id;
} MyStruct_default = {3};

typedef struct MyStruct_s MyStruct;

そして、常に新しいインスタンスを次のように初期化します。

MyStruct mInstance = MyStruct_default;

3
グローバル配列 'MyStruct arr [MAX_SIXE];'がある場合、関数はどのように使用できますか?(注:すべてのメンバーを
通過し

10
MyStruct_defaultはconstとして宣言する必要があります。
Lundin 2012

1
ご回答有難うございます。オンラインそれをテストするためのコードのサンドボックスを作ってしまった、最初にすべてを接続する手間を持っていた、これは他の誰かに役立ちます願っています:ideone.com/knQ7xS
HoldOffHunger

52

あなたはこのようにそれを行うことはできません

代わりに以下を使用してください

typedef struct
{
   int id;
   char* name;
}employee;

employee emp = {
.id = 0, 
.name = "none"
};

マクロを使用して、インスタンスを定義および初期化できます。これにより、新しいインスタンスを定義して初期化するたびに簡単になります。

typedef struct
{
   int id;
   char* name;
}employee;

#define INIT_EMPLOYEE(X) employee X = {.id = 0, .name ="none"}

従業員タイプで新しいインスタンスを定義する必要がある場合のコードでは、次のようにこのマクロを呼び出すだけです。

INIT_EMPLOYEE(emp);

1
パラメータへのパスが要件を満たしていない場合は、良くないようです。

18

Cで構造体を定義するときに初期化できないというAlsに同意します。ただし、以下に示すように、インスタンスの作成時に構造体を初期化することはできます。

Cでは、

 struct s {
        int i;
        int j;
    };

    struct s s_instance = { 10 ,20 };

C ++では、以下に示す構造の定義に直接値を与えることが可能です。

struct s {
    int i;

    s(): i(10)
    {
    }
};

13

できるよ:

struct employee_s {
  int id;
  char* name;
} employee_default = {0, "none"};

typedef struct employee_s employee;

そして、新しい従業員変数を宣言するときに、デフォルトの初期化を行うことを忘れないでください。

employee foo = employee_default;

または、ファクトリ関数を介して常に従業員構造体を作成することもできます。


8

使用しているgcc場合はdesignated initializers、オブジェクトの作成を与えることができます。

typedef struct
{
   int id=0;
   char* name="none";
}employee;

employee e = 
{
 .id = 0;
 .name = "none";
};

または、単に配列の初期化のように使用します。

employee e = {0 , "none"};


1
:私はもっとこの質問では、いくつかのコードも指定された初期化子のためにコロンを使用し見てきたstackoverflow.com/questions/1601201/...
sdaau

7

他の回答が述べているように、デフォルトの構造体を作成します。

struct MyStruct
{
    int flag;
}

MyStruct_default = {3};

ただし、上記のコードはヘッダーファイルでは機能しません-エラーが発生します:multiple definition of 'MyStruct_default'。この問題を解決するexternには、代わりにヘッダーファイルで次を使用します。

struct MyStruct
{
    int flag;
};

extern const struct MyStruct MyStruct_default;

そしてcファイル内:

const struct MyStruct MyStruct_default = {3};

これがヘッダーファイルに問題がある人に役立つことを願っています。


数年後のコメント:ヘッダーファイルでこれを直接実行できれば、おそらくもっと理にかなっています。
David Callanan

5

さらに、既存の回答を追加するには、構造体初期化子を非表示にするマクロを使用できます。

#define DEFAULT_EMPLOYEE { 0, "none" }

次に、コードで:

employee john = DEFAULT_EMPLOYEE;

3

初期化関数を実装できます。

employee init_employee() {
  empolyee const e = {0,"none"};
  return e;
}

C構造体変数オブジェクトe(constまたはnot)は、それが定義されているブロックが終了すると消えることに注意してください。ポインタの場合、ダングリングポインタの問題が発生します。したがって、戻り値の型がポインターの場合、これは適切な解決策ではありません。最良の方法は、C構造体初期化子を使用して、デフォルト値を持つ静的グローバル構造体変数オブジェクトを作成し、変数のset関数とget関数を使用して、プログラムの実行時に値を変更することです。または、ローカル構造体変数オブジェクトをパラメーターとして集合関数に渡し、集合関数内でそのプロパティ値を変更します。
ecle 2017

2
申し訳ありませんが、@ ecleは間違っています。戻り値は裸の構造体であり、ポインタではありません。参照によって返されるのではなく、コピーされます。正直なところ、コンパイラはおそらくそれを最適化するでしょう。
ビットマスク2017

@bismask誤解しないでください..関数がポインターである場合にポインターを返すかどうかについては言及しました。私の最近の編集の前に、あなたは私の前のコメントにコメントしたかもしれません。
ecle 2017

2

次のように、いくつかの関数を使用して構造体を初期化できます。

typedef struct
{
    int flag;
} MyStruct;

MyStruct GetMyStruct(int value)
{
    MyStruct My = {0};
    My.flag = value;
    return My;
}

void main (void)
{
    MyStruct temp;
    temp = GetMyStruct(3);
    printf("%d\n", temp.flag);
}

編集:

typedef struct
{
    int flag;
} MyStruct;

MyStruct MyData[20];

MyStruct GetMyStruct(int value)
{
    MyStruct My = {0};
    My.flag = value;
    return My;
}

void main (void)
{
    int i;
    for (i = 0; i < 20; i ++)
        MyData[i] = GetMyStruct(3);

    for (i = 0; i < 20; i ++)
        printf("%d\n", MyData[i].flag);
}

2
構造体のグローバル配列が必要な場合、GetMyStruct()をどのように呼び出すことを提案しますか?
user1508893 2012

GetMyStructはmallocを使用すべきではありませんか?
ドミトリー


1

この構造を1回だけ使用する場合、つまりグローバル/静的変数を作成する場合は、を削除してtypedef、この変数を即座に初期化できます。

struct {
    int id;
    char *name;
} employee = {
    .id = 0,
    .name = "none"
};

その後、employeeコードで使用できます。


0

構造体の初期化関数は、構造体にデフォルト値を付与するための良い方法です。

Mystruct s;
Mystruct_init(&s);

またはさらに短い:

Mystruct s = Mystruct_init();  // this time init returns a struct

グローバル配列 'MyStruct arr [MAX_SIXE];'がある場合、関数はどのように使用できますか?(注:すべてのメンバーを
通過し

0

デフォルト値への別のアプローチ。構造体と同じ型で初期化関数を作成します。このアプローチは、大きなコードを別々のファイルに分割するときに非常に役立ちます。

struct structType{
  int flag;
};

struct structType InitializeMyStruct(){
    struct structType structInitialized;
    structInitialized.flag = 3;
    return(structInitialized); 
};


int main(){
    struct structType MyStruct = InitializeMyStruct();
};

0

そのための関数を作成できます。

typedef struct {
    int id;
    char name;
} employee;

void set_iv(employee *em);

int main(){
    employee em0; set_iv(&em0);
}

void set_iv(employee *em){
    (*em).id = 0;
    (*em).name = "none";
}

0

別のアプローチは、構造体で許可されている場合、デフォルト値を内部に持つ#defineを使用することです。

#define MYSTRUCT_INIT { 0, 0, true }

typedef struct
{
    int id;
    int flag;
    bool foo;
} MyStruct;

使用する:

MyStruct val = MYSTRUCT_INIT;

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.