• ベストアンサー

構造体の構造体配列初期化

typedef strunct _test01 { int a; int b; } test01_t; typedef strunct _test { int c; test01_t sTest01[256]; } test_t; test_t sTest; 上記のような構造体がある場合、sTestのメンバのsTest01をNULL初期化する 方法とsTest01に値が入っていないか(初期化されているか)を判定する方法を 教えていただけませんか? よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

C言語の場合、グローバル変数として宣言したら0で全部の値が埋められており、ローカル変数として宣言したら、そのときにスタックにあった無意味な値 (いわゆるゴミ) が入っています。 NULL初期化というのが何を意味にしているのかよくわかりませんが、0で埋めるということだったら、bzeroやmemsetを使えばよいと思います。面倒くさいのでtest_tのcの値も0にしますが、こうすると0で埋められるでしょう。 bzero(&sTest; sizeof(sTest)); あるいは、sTest01の値が割り当てられていない状態にするということなら、書き方が違います。C言語はJavaなどと違い、配列には参照ではなく実際の値が入ります。よって、上記のように宣言するとsTest01はtest01_t の大きさ * 256のメモリー領域が自動的に確保されます。 もし、Javaなどのように参照の配列を作りたかったら、ポインタの配列にすることです。 typedef strunct _test { int c; test01_t *sTest01[256]; } test_t; test01_tの後に*が入っていることに注目してください。この場合も、初期化には次のコードでOKです。 bzero(&sTest; sizeof(sTest)); こうすると、sTest01[0]などには(test01_t*)0が設定されていますが、これでポインタの指し先がないことを示せるので。 具体的には、初期化されているか判定するコードはこんな感じです。 if (sTest.sTest01[0] == NULL) { ... } NULLは(void*)0ですが、void*はどのポインタにもなれるというオールマイティな値なので、この比較でOKです。よって、C言語ではmallocやcallocもcastは不要です。 (余談ですが、C++ではキャストがいりますが、そもそもmalloc、callocで普通メモリーを確保しません) この場合、各エントリーの新規割り当ては次のようにして行わなくてはなりません。 sTest.sTest01[0] = malloc(sizeof(test01_t)); また、C言語にはGCが無いので、sTestの値を使わなくなるときに一つ一つfreeしなくてはなりません。これをし忘れると、メモリーリークが起き、プログラムを動かすごとに使えないメモリーが増えていき、仕舞いには、メモリーが確保できなくなってプログラムが異常終了します。 free(sTest.sTest01[i]); 自分だったら、一つ一つ書いているとどうしてもミスするので、この構造体の確保と解放のための関数くらいは書くかもしれません。

その他の回答 (3)

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.4

>上記のような構造体がある場合、sTestのメンバのsTest01をNULL初期化する >方法とsTest01に値が入っていないか(初期化されているか)を判定する方法を >教えていただけませんか? 他の方もいわれてますがNULL初期化とは何をすることをいわれてますか? 「NULLポインタで初期化」であれ「NUL文字で初期化」であれsTest01の初期化にはあいませんが。 もし仮にsTest01を以下のようにポインタの配列とした場合 test01_t *sTest01[256]; sTest01の(NULLポインタでの)初期化を memset(sTest01, 0, sizeof(sTest01)); /* bzero(sTest01, sizeof(sTest01)); と同義 */ のようにするのは厳密にいえばダメです。 C言語の規格上、0はNULLポインタとして扱われますがNULLポインタは0とは限らないので(0でない処理系もあります)。 面倒でも for (int i = 0; i < sizeof(sTest01) / sizeof(sTest01[0]); i++) { sTest01[i] = NULL; } の方がよいです。 変数が初期化されているかされていないかの判定方法はC言語ではありません。 ゴミだろうが何だろうが何らかの値は必ず入ってますので。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

>sTestのメンバのsTest01をNULL初期化する方法 NULLで初期化したいのでしょうか? 0で初期化したいのでしょうか? NULLと0とは意味が異なります。 >sTest01に値が入っていないか(初期化されているか)を判定する方法 値が入っていないかどうかを判定することは、できないのではないかと思います。 というのは、仮に0で初期化した場合、 0という値が「入っている」のであって、「何も値が入っていない」ことにはならないからです。 0という値が入っているかどうかを判定することならば、できます。

  • black2005
  • ベストアンサー率32% (1968/6046)
回答No.1

Null初期化って何? 値が入っていないこともあり得ない 必ず初期値あるいはゴミが入る

関連するQ&A

  • CStringを含むconst構造体

    VC++6.0で typedef struct { int i; CString s; } StructTest; という構造体を作ったとして const StructTest m_STest = { 1, "TEST" }; とすると 『error C2552: 'm_STest' : 初期化子リストによる個別の識別子の初期化に誤りがあります。』 と出ます。 このような記述は出来ないのでしょうか?

  • 構造体メンバ 構造体ポインタ 値代入

    typedef struct _test_t{ int aaa; int bbb; } test_t; typedef struct _globalData{ int xxx; test_t* pTestData[256]; } globalData_t; globalData_t globalData; int main(){ test_t testData1 = {1,1}; test_t testData2 = {2,2}; *globalData.pTestData[1] = testData1; /* (1) */ globalData.pTestData[2] = &testData1; /* (2) */ } 上記のようなグローバルデータの構造体globalData のメンバの構造体配列にtest_t型の構造体を格納し保持するには、 (1)、(2)のどちらが正しいでしょうか?

  • 多次元配列の構造体の初期化

    タイトル通りです。やり方がわかりません。 構造体変数の初期化や多次元配列の初期化が載ってるページは多いのですが、コレだけは調べても解りませんでした。 typedef struct{ int flag; ~~~~~(略)~~~ }map_t; map_t map[64][64]; の後、map_t型のmap64*64の int flag全てに値を代入したいのですが 詳しいやり方が解りません。 int hensuu[3][3]={   {1,2,3},{4,5,6},{7,8,9} }; 普通の多次元配列みたいにmこんな感じでやりたいんですけど… 初心者でスミマセン。回答いただけたらありがたいです。

  • C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成して

    C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成しています。 一応目的の動作はするのですが、プログラミングとして正しいか教えて頂ければと 思います。 <test.c> int main() { /* ---------------------------------------- */ /* 構造体のメンバ(NULL保障無し)がNULLか */ /* 比較するサンプル */ /* ---------------------------------------- */ char buf[50]; /* サンプル構造体 */ struct ST_test { int cd; char name[10]; int no; }; struct ST_test st_test; /* 構造体定義 */ memset(&st_test,0x00,sizeof(st_test)); /* 構造体初期化 */ memset(&buf[0],0x00,sizeof(buf)); /* 構造体初期化 */ /* 構造体に値セット */ st_test.cd = 12; memcpy(&st_test.name[0],"aabbccddee",sizeof(st_test.name)); st_test.no = 999; /* NULL判定 */ if(*st_test.name == 0x00) { printf("NULLです\n"); } else { printf("NULLではないです\n"); } return (0); }

  • 構造体のメンバが配列の場合の扱い

    typedef struct _info_t{ int xxx; int yyy; int zzz; } info_t; typedef struct _gData{ int aaa;  int bbb; info_t infoData[100]; } gData_t; gData_t gMainData; 質問1 C言語で上記のようなグローバルのデータを作成しようとしています。 gMainDataの中身を初期化するにはどうするのがベストでしょうか? (特にinfoData[100]の初期化) 質問2 gMainData.infoData[XXX]には info_t型のtmpDataを代入しようとしていますが gMainData.infoData[XXX] = tmpData; データがはいっているかどうかはどう判定するべきでしょうか? 質問3 以下のようにポインタを使うのは間違いでしょうか? typedef struct _gData{ int aaa;  int bbb; info_t *infoData[100]; } gData_t; 初期化 memset(gMainData.infoData,NULL, 100); データの代入 *gMainData.infoData[XXX] = tmpData; データの有無判定 if( gMainData.infoData[XXX] == NULL){ }

  • 動的な構造体配列の初期化

    以下のように構造体を new で動的に確保したときに 構造体の中身(char bbb[10], int ccc)をゼロで初期化したいのですが ZeroMemory を使用するとCArrayのAdd()を使用したときにエラーになってしまいました。 何かよい方法がありましたら教えて下さい。お願いいたします。 # 簡単にイメージですが・・・ typedef struct { CString a; CString b; }aaa_t ; struct s_aaa{ char bbb[10]; int ccc; CArray<aaa_t,aaa_t> m_aaaArray ; } s_aaa *StructB; StructB = new s_aaa [10];

  • 構造体配列の初期化について

    C初心者です。 宜しくお願い致します。 某社のSDKを参考にプログラムを作成しておりますが、構造体配列の初期化する方法がわからなくて困っています。 下記の構造体の初期化をしたいのですが、どのような方法で初期化すればいいかわからない状態です。 すいませんが、ご教授いただきたく宜しくお願い申し上げます。 typedef struct ioctl_videomode { V2U_INT32 width; V2U_INT32 height; V2U_INT32 vfreq; } V2U_PACKED V2U_VideoMode; typedef struct v2u_rect { V2U_INT32 x; V2U_INT32 y; V2U_INT32 width; V2U_INT32 height; } V2U_PACKED V2URect; typedef struct ioctl_grabframe2 { void * pixbuf; V2U_INT32 pixbuflen; V2U_UINT32 palette; V2URect crop; V2U_VideoMode mode; V2U_INT32 imagelen; V2U_INT32 retcode; } V2U_GrabFrame2; typedef struct { V2U_GrabFrame2* frame; char ftime[16]; }frameinfo; void main() { frameinfo fr[512]; //初期化したい →→ fr = (frameinfo*)malloc(sizeof(frameinfo)*512); } error C2106: '=' : 左のオペランドが、左辺値になっていません

  • 構造体のメンバ初期化について

    構造体のメンバを初期化したいのですが、 メンバ数が多いので1個ずつ初期化するのは面倒です。 そのため、一度に初期化する方法を探していたのですが、 memsetやZeroMemoryなどで可能だということが解りました。 しかし、パディング等の問題を含めて この関数を使用しても問題ないのでしょうか? 以下に例を挙げます。 typedef struct SAMPLE {  char a;  int b;  int c;  float d;  SAMPLE(){   ZeroMemory( this, sizeof(Sample) );  } } Sample; 構造体Sampleは32bitマシンでは 一見13byteに見えますが、パディングが入るので、 実際にはsizeof(Sample)は16byteと表示されます。 また、構造体には自動的に初期化と解放するための、 コンストラクタ・デストラクタのみがあり、 関数や仮想関数などの実装はありません。 この方法の安全性について、 ご存知の方がいらっしゃればアドバイスいただけると助かります。 よろしくおねがいします

  • 構造体の静的な初期化

    構造体の静的な初期化で、初期化が書かれていないメンバーは、 どうなるのでしょうか。。? たとえば・・・ // 構造体の宣言 strcut MY_STRUCT {    int data1 ;    int data2 ;    int data3 ;    int data4 ; } ; // 変数宣言&初期化 static strcut MY_STRUCT st = {    .data1 = 100,    .data3 = 300 } ; ネットで調べると、 初期化で指示されていないメンバーは0に初期化される、 という記述も一つだけ見つけたのですが・・・これはC言語(C99)の仕様でしょうか? それともコンパイラ依存の仕様でしょうか?

  • qsortを用いた構造体配列のソート

    お世話になります。 http://simd.jugem.jp/?eid=116 を参考にqsortを用いた構造体配列のソートをC言語で記述しようとしています。 上記のページは、構造体のメンバが配列でない場合です 今回は、メンバが配列のときの構造体配列のソートを実現したいと思っています。 つまり、 typedef struct{ int a; int b[1024]; int c[1024]; }TEST; という構造体配列があって、 TEST base[256]; と宣言し、メンバの配列の添え字を基準としてソートしたいときには、どのようにqsortを用いれば良いのでしょうか、ということです。 どうしたらよいかわからず途方にくれています。 つまり、下のようなソートが行われるには、どのようなプログラムを書けばいいかということです。 構造体でソートするものとします。 構造体でソートできれば、qsortを使っていなくても構いません。 プログラムの得意な方がおりましたら、ご教授下さい。 <ソート前> //************************************************ test[ 0].b[0] = 3; test[ 1].b[0] = 102; ... test[255].b[0] = 1; ------------ test[ 0].b[1] = 99; test[ 1].b[1] = 200; ... test[255].b[1] = 2; ------------ ... ------------ test[ 0].b[1023] = 99; test[ 1].b[1023] = 9; ... test[255].b[1023] = 200; //************************************************** <ソート後>:test[x]ではなく、b[y]を基準としてそれぞれのくくりをソートしたい //************************************************ test[ 0].b[0] = 1; test[ 1].b[0] = 3; ... test[255].b[0] = 102; ------------ test[ 0].b[1] = 2; test[ 1].b[1] = 99; ... test[255].b[1] = 200; ------------ ... ------------ test[ 0].b[1023] = 9; test[ 1].b[1023] = 99; ... test[255].b[1023] = 200; **************************************************