グローバルデータの構造体配列にデータを格納する方法

このQ&Aのポイント
  • グローバルデータの構造体配列にデータを格納する方法について質問です。
  • 質問の中にある(1)と(2)のコードのどちらが正しいか教えてください。
  • また、グローバルデータの構造体配列にはどのようなデータを格納するのですか?
回答を見る
  • ベストアンサー

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

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)のどちらが正しいでしょうか?

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

  • ベストアンサー
  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.4

> 代入、*globalData.pTestData[xxx] = testData1; > 削除 *globalData.pTestData[xxx] = NULL; 削除時点でヌルポインタになってしまうので、ご所望の書き方では削除後に代入はできません。 ちなみに削除はアスタリスクを取って globalData.pTestData[xxx] = NULL; が正しいと思います。 なぜNULLを代入したいのでしょうか? 「もしNULLなら構造体の値を代入」などの処理をしたいのであれば、まずはNULLのポインタに 領域を確保するか、すでに確保されているアドレスを代入することになります。 ご所望の代入方法をするためには、まず「領域の確保」が必要です。 これを踏まえて、代入と削除を書くと以下のようになるかと思います。 #include <stdio.h> #include <string.h> 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 }; test_t testDataBuf[256]; int i; for(i=0; i<256; i++) globalData.pTestData[i] = &testDataBuf[i]; // 代入 *globalData.pTestData[1] = testData1; /* (1) */ // delete globalData.pTestData[1] = NULL; // 再代入 globalData.pTestData[1] = &testDataBuf[1]; // NULL状態を解消 *globalData.pTestData[1] = testData1; } しかし、これは無駄な処理に見えます。 このコードを読んだ人は「なぜDeleteがNULL代入なのだろうか?」と疑問に思うかもしれません。 私ならば・・・ 案1 aaaが-1なら未使用というルールにして #define delete_test_t(x) (x.aaa = -1) #define is_enable(x) (x.aaa != -1) とかで管理しといて、あとでソース読むのが楽になるようにケアすると思います。 案2 DeleteでNull代入する代わりにtest_t構造体に使用中フラグを追加 alloc禁止の前提ではこんなところですかね。

その他の回答 (3)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> 構造体globalDataのメンバの構造体配列にtest_t型の構造体を格納し保持する をどんな意味で使っているか、によって「正解」が変わります。 (1)は ポインタ globalData.pTestData[1] が示す実体(test_t構造体)に、testData1の内容をコピーする (2)は ポインタ globalData.pTestData[2] の値を testData1のアドレスにする。 の意味です。 ○ testData1のアドレスを覚えさせたい。 testData1.aaa=5 としたら、 global.pTestData[n].aaaも5になるようにしたい。 → (2)のような形が正解 ○ 現時点でのtestData1の中身を覚えさせたい。(コピーを保存しておきたい) 後に testData1.aaa=5 としても、 global.pTestData[n].aaaは記憶させた時点の1のままになるようにしたい。 → 形は (1)が正解だが、今のままだとpTestData[2]が示す先にが入るべき領域が確保されていないので、期待通りに動かない。

shin2072
質問者

補足

丁寧な回答ありがとうございます。 >○現時点でのtestData1の中身を覚えさせたい。(コピーを保存しておきたい) グローバルデータに現時点でのtestData1の中身を保存しておきたく、 (1)のように実体を保存しようと思いました。 できれば配列を初期化時などに実体を一括して確保しておく方法はないでしょうか? javascript:void(0); ポインタ型の構造体メンバでは不可能でしょうか? よろしくお願い致します。

  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.2

この例では(2)が正しいです。 (1)ではpTestData[1]が指すアドレスが不定な値にもかからわず、 その領域にtestData1の値を書き込もうとしています。 以下のようにすればどちらでも通ります。 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] = malloc(sizeof(test_t)); *globalData.pTestData[1] = testData1; /* (1) */ globalData.pTestData[2] = &testData2; /* (2) */ // check printf("%d\n", globalData.pTestData[1]->aaa); printf("%d\n", globalData.pTestData[2]->aaa); }

shin2072
質問者

補足

サンプルコードまでつけていただきまして、ありがとうございます。 申し訳ありませんが、もうひとつ質問させてください。 グローバルの構造体のポインタメンバに値を格納する場合 >(1)ではpTestData[1]が指すアドレスが不定な値にもかからわず、 >その領域にtestData1の値を書き込もうとしています。 は理解しました。 他の複数の関数でも、同じようにグローバルデータに値を 代入、*globalData.pTestData[xxx] = testData1; 削除 *globalData.pTestData[xxx] = NULL; をしようとしています。 できれば、malloc,freeによる動的確保、解放をおこなわず、 一括して領域を確保しておく方法はないでしょうか?

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

実行してみました? >*globalData.pTestData[1] = testData1; globalData.pTestData[1]のポインタが指す先にtestData1をコピーする。 となり、 >globalData.pTestData[2] = &testData1; globalData.pTestData[2]にtestData1のアドレスを格納する。 となります。 さて、(1)の時にglobalData.pTestData[1]のポインタは「中身を格納できる領域」を指していますか?? # コードとして掲示されていないけど、「どこか必要な場所を指している」のであれば問題ないでしょうが。

関連するQ&A

  • 入れ子の構造体について

    例えば、入れ子の構造体を1つ使いたい場合、 struct bbb{ int b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; と書くと、「dt.a.b = 10」とやれば、値等を設定できると思いますが、 入れ子の構造体を2つ使いたい場合も、同じように書けるのでしょうか? struct ccc{ int c; }; struct bbb{ struct ccc b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; dt.a.b.c = 10; と書けるのでしょうか?こんがらがってしまって、どう書いていいのか・・。 2つでも出来るのであれば、コードの書き方を教えて頂けませんか?

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

    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];

  • 構造体の型について

    ある構造体をxxxと名づける以下のプログラムを作成しました。 ーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx aaa; strcpy(aaa.variable,"bbb"); printf("%s\n",aaa.variable); } ーーーーーーーーーーー これは動き、bbbと表示されます。 しかしながら、構造体のポインタを使用した 以下のプログラムではコンパイルはとおりますが実行時にコアダンプして落ち ます。 ーーーーーーーーーーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx* aaa; strcpy(aaa->variable,"bbb"); printf("%s\n",aaa->variable); } ーーーーーーーーーーーーーーーーーーーーーーー 両プログラムの意図はまったく同じなのに何故いけないのでしょうか。

  • 配列から構造体へデータコピー

    配列から構造体へデータのコピーをしたいのですが、 構造体のメンバがビットフィールドで構成されている時の処理がわかりません。 --------test.c----------- #include <stdio.h> #include <string.h> typedef struct{ unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned int ddd :13; unsigned char eee :2; unsigned char fff :2; unsigned char ggg :4; }test_t; int main(void) { test_t test_t; unsigned char data[]={0x5F, 0xFE, 0x1C}; memcpy(&test_t, data, 4); printf("aaa = %X\n", test_t.aaa); printf("bbb = %X\n", test_t.bbb); printf("ccc = %X\n", test_t.ccc); printf("ddd = %d\n", test_t.ddd); printf("eee = %X\n", test_t.eee); printf("fff = %X\n", test_t.fff); printf("ggg = %X\n", test_t.ggg); return 0; } ------期待出力--------- aaa = 0 bbb = 1 ccc = 0 ddd = 1FFE eee = 0 fff = 1 ggg = 12 「test.c」を実行した時に「期待出力」のような出力を期待していたのですが、実際には aaa = 1 bbb = 1 ccc = 1 ddd = 1 eee = 0 fff = 0 ggg = 0 と表示されてしまいます。 ビットフィールドで構成された構造体に、配列の値をそのままあてる事は出来ないのでしょうか? 出来るだけ、マスクやシフト演算を使用しないで、配列からビット単位で値を抽出したいのですが・・・

  • 構造体のあるメンバを基準にソートするには?

    以下のように定義した構造体(下の構造体は入れ子になっている)を必要な時に動的に割り当てた後(デー多数は不定)、たとえば、商品価格を基準に降順、昇順に並び替える機能を追加したいのですが、どのように解決したらよろしいでしょうか? /* 現在の日時を格納する構造体 */ typedef struct time_type{ int year; int month; int day; }time_type; /* 商品の情報を格納する構造体 */ typedef struct shohin_type{ int code; /* 商品コード */ int price; /* 商品価格 */ char *name; /* 商品名 */ int flag; /* フラグ */ struct time_type date; /* 登録日 */ struct shohin_type *before; /* 前の構造体のアドレス */ struct shohin_type *next; /* 次の構造体のアドレス */ }shohin_type;

  • 構造体メンバへの代入

    とても初歩的なことなのですが、 typedef struct _X{ int x; }X[50]; と構造体を定義して X[0].x = 0; と0を代入しようとすると、「宣言が正しく終了していない」とエラーが出てしまいます。 これはなぜでしょうか? ちなみにMicrosoft Visual C++ 2005 Express Editionを使っています。

  • 構造体を型の異なる構造体に代入

    C言語初心者です。 今回の質問は入力された構造体のメンバのデータを型の異なる構造体に代入したいのですが、毎回コンパイラにおこられてしまいます(汗)具体的には typedef struct MSG{ longint type; int flg; int Dt[64]; }t_msg; このDt[64]を以下の構造体に代入します。 typedef struct SC_MSG{ char a; char b; short c; char d; char e; short f; }t_sc_msg; その際、異なる関数で処理するため、 main(){ foo(&t_msg); }; void foo(t_msg *pt_msgdt){ t_sc_msg = (*pt_msgdt+8); ココがエラーになってしまいます。 何か、根本的な間違いをおかしている気がします。 ご指導の方、宜しくお願いします。 ちなみにOSはLinuxでコンパイラーはgccです。

  • ポインタを使って構造体の配列を戻り値にするには

    関数の戻り値を構造体の配列(アドレスを受け渡しを利用して)にしたいのですがうまくゆきません。 以下のプログラムではコンパイルはできるのですが、 a0 = 2 a1 = 4198512 a2 = 4329332 と表示されてしまいa1,a2がうまくゆきません。 ********************************************* #include<stdio.h> struct test{ int a; }; struct test *func(void); void main(void) { struct test *data;//構造体ポインタ int i; data = func(); //ポインタにtest関数の戻り値(アドレス)を代入 for(i=0;i<=2;i++){   printf("a%d = %d\n",i,(data+i)->a); //構造体要素を表示 } } struct test *func(void) { struct test data[3]={1,2,3}; //構造体配列を定義 return (&data[0]); //構造体配列の先頭アドレスを返す } ************************************************* test関数から受ける取ったアドレス(&data[0])をポインタ(data)に代入して1づつずらして表示させれば a0=1,a1=2,a=3 となると思ったのですがどこが間違っているのでしょうか? よろしくお願いします。

  • 構造体の引数について

    struct XXX { char *aaa; char *bbb; }; static struct XXX YYY[] = { {NULL, "JJJ"}, ... }; 上記のYYY[]をmainの上で設定し、下記のように使いたいです。 sub()関数でYYYの値を見たいのですが、下記の設定ではコンパイルが通りません。 どうしたらsub()関数で使うことができますか? どなたかご教授ください。 main(){ rtn = sub((struct xxx *)YYY); } int sub(struct xxx *YYY[10]){ for(i=0; YYY[i]->bbb[0]; iii++){ ... } ... }

専門家に質問してみよう