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)のどちらが正しいでしょうか?
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禁止の前提ではこんなところですかね。
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]が示す先にが入るべき領域が確保されていないので、期待通りに動かない。
この回答への補足
丁寧な回答ありがとうございます。
>○現時点でのtestData1の中身を覚えさせたい。(コピーを保存しておきたい)
グローバルデータに現時点でのtestData1の中身を保存しておきたく、
(1)のように実体を保存しようと思いました。
できれば配列を初期化時などに実体を一括して確保しておく方法はないでしょうか?
javascript:void(0);
ポインタ型の構造体メンバでは不可能でしょうか?
よろしくお願い致します。
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);
}
この回答への補足
サンプルコードまでつけていただきまして、ありがとうございます。
申し訳ありませんが、もうひとつ質問させてください。
グローバルの構造体のポインタメンバに値を格納する場合
>(1)ではpTestData[1]が指すアドレスが不定な値にもかからわず、
>その領域にtestData1の値を書き込もうとしています。
は理解しました。
他の複数の関数でも、同じようにグローバルデータに値を
代入、*globalData.pTestData[xxx] = testData1;
削除 *globalData.pTestData[xxx] = NULL;
をしようとしています。
できれば、malloc,freeによる動的確保、解放をおこなわず、
一括して領域を確保しておく方法はないでしょうか?
No.1
- 回答日時:
実行してみました?
>*globalData.pTestData[1] = testData1;
globalData.pTestData[1]のポインタが指す先にtestData1をコピーする。
となり、
>globalData.pTestData[2] = &testData1;
globalData.pTestData[2]にtestData1のアドレスを格納する。
となります。
さて、(1)の時にglobalData.pTestData[1]のポインタは「中身を格納できる領域」を指していますか??
# コードとして掲示されていないけど、「どこか必要な場所を指している」のであれば問題ないでしょうが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# C言語(構造体) 3 2022/07/05 20:08
- C言語・C++・C# C言語 2 2022/07/21 00:02
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- その他(芸能人・有名人) 小林幸子の話 1 2022/07/21 19:44
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エラーの意味は? Lvalue req...
-
C言語 列挙型(enum型)変数について
-
テキストボックスの値を変数に...
-
C言語 アロー演算子について質...
-
VBAでダブルコーテーション入り...
-
7行テトリスコードで分からな...
-
Variant型で宣言してるのにEmpt...
-
EXCEL/VBA 変数の値をクリップ...
-
i++と++i ってどう違うのですか?
-
verilog HDLの[=]と[<=]の使い分け
-
VB6.0 DataGridでのfirstRowの...
-
VBA 1行で複数の代入を行った...
-
C言語(高校1年の内容)について
-
画像のプログラムに関して質問...
-
初心者が簡単なPowerShellスク...
-
Access2003 オートナンバーの現...
-
Excel-vba 文字列と変数を...
-
初心者プログラミング
-
VisualStudio2022でC言語プログ...
-
プログラミングについての質問...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAでダブルコーテーション入り...
-
エラーの意味は? Lvalue req...
-
C言語 列挙型(enum型)変数について
-
EXCEL/VBA 変数の値をクリップ...
-
整数xxxが大き過ぎますというエ...
-
テキストボックスの値を変数に...
-
[VBS]変数を定数に変換する方法...
-
Variant型で宣言してるのにEmpt...
-
jsp~jspにhiddenを使って変数...
-
processing エラーで、 "cannot...
-
python の 連鎖代入の文法
-
i++と++i ってどう違うのですか?
-
プログラミングで変数と関数の...
-
C言語 アロー演算子について質...
-
「%」を使って、偶数か奇数かを...
-
JavaScriptをURLから直接実行し...
-
VBA 1行で複数の代入を行った...
-
ExcelのVBAでをA列に第0〜19項...
-
無名関数のメリットがよくわか...
-
コマンドプロンプト バッチ|結...
おすすめ情報