痔になりやすい生活習慣とは?

構造体の中にvoid*型のポインタを作り、そこの中身を替えることでデータを変えたいと思っています。


struct DATA{
void* p;
}

struct PROF_1{
char* name;
int age;
}

struct PROF_2{
char* name;
int age;
int level;
}


void main(){
struct DATA data;
struct PROF_1 p1={"HATOYAMA", 60};
struct PROF_2 p2={"OBAMA", 60, 1};

data.p = p1;
printf("Name[%s] Age[%d]\n", (PROF_1)(data.p)->name, (PROF_1)(data.p)->age);

data.p = p2;
printf"Name[%s] Age[%d] Lv[%d]\n", (PROF_2)(data.p)->name, (PROF_2)(data.p)->age, (PROF_2)(data.p)->level);
}

このような感じで構造体の中にあるvoid*型のポインタの参照する場所を変えるだけで構造体の中身を変化させることが出来ないでしょうか?

A 回答 (2件)

>void*型のポインタの参照する場所を変えるだけで構造体の中身を変化させることが出来ないでしょうか?


できます。
使用する型がわかっているのであればunionで定義する方法もありますが。
struct DATA{
 int type;  // 入れている型
 union
 {
  struct PROF_1 data1;
  struct PROF_2 data2;
 }packet;  // 供用の定義
}
とか。
もちろんポインタも使用できます。
    • good
    • 0
この回答へのお礼

なるほど、共用体を使えばいいのですね。
ありがとうございます。

お礼日時:2010/02/03 10:48

もちろんできます.


ただし, 「現在入っているのはどの型なのか」をきちんと意識する必要はあります.
    • good
    • 0
この回答へのお礼

楽をするにはどこかで苦労する必要があるのですね。

お礼日時:2010/02/03 10:47

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qvoid型のポインタで構造体の参照

void型のポインタで構造体や共用体を参照することはできますか?

void *p=&kou;
struct KOU kou;
(struct KOU*)kou.name="名前";

のようにして構造体を参照しようとしたのですが、「左側が構造体又は共用体ではありません。」と出ます。型キャストはコンパイラに型を知らせるだけのものなのでコンパイラが構造体の型を知ることができない、ということでしょうか?void型のポインタを使って構造体(共用体)を参照することはできますか?回答よろしくお願いします。

Aベストアンサー

#1さんへの返答の通りのコードだとすると、void*で構造体を参照することはできません。
構造体をコンパイラがどのように認識しているかという話になるのですが、簡単に言うと、構造体の情報からメンバー変数の位置を計算しているので、void*だとその位置の計算ができないのです。

Q構造体を指すポインタからその中のポインタ変数が指す要素の参照

構造体を指しているポインタから、
その構造体内にあるポインタ変数の指している要素に値を代入する方法が、どうしてもわかりませんでした。
どなたか助けてください、お願いします。


struct Kouzou
{
int* p;
};

int main()
{
Kouzou kou;
Kouzou* k_p;

k_p = &kou;

k_p -> *p = 10; //エラー
}

Aベストアンサー

*k_p->p = 10;

ですけど、pが指す先を定義しておかないと
エラーになりますよ。

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

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

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){

}

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;
データがはいっているかどう...続きを読む

Aベストアンサー

1.初期化
ループでもmemsetでもよいと思います。どれがベストかはケース・バイ・ケースでしょう。

ただしmemsetの第2引数はint型、第3引数はバイト数なので、次のようにするべきです。
memset(gMainData.infoData, 0, 100 * sizeof(info_t));

また、C言語の規格により static 変数を明示的に初期化しなければ全て 0 になるので
static gData_t iniData;
gData_t data;
と定義しておいて
data = iniData;
のように初期化する方法も(一応)あります。


2.データの代入

info_t *infoData[100] は構造体の配列ではなく、ポインタの配列です。
infoData をポインタにするなら、構造体を下のようにすれば

typedef struct _gData {
 int aaa;
 int bbb;
 info_t *infoData[100];
 info_t _infoData[100];
} gData_t;

次のように代入することができます。

data._infoData[XXX] = tmpData;
data.infoData[XXX] = &(data._infoData[XXX]);


3.データの有無判定

前述の2のようにすれば
if( gMainData.infoData[XXX] == NULL){
}
でデータを代入済みかどうか判定できます。
もちろんデータを代入していないポインタがNULLであることが前提ですが。


・余談ですが、構造体のタグ名とtypedefする型名は同じでも大丈夫です。例えば

typedef struct info_t{
...
} info_t;

のように。

1.初期化
ループでもmemsetでもよいと思います。どれがベストかはケース・バイ・ケースでしょう。

ただしmemsetの第2引数はint型、第3引数はバイト数なので、次のようにするべきです。
memset(gMainData.infoData, 0, 100 * sizeof(info_t));

また、C言語の規格により static 変数を明示的に初期化しなければ全て 0 になるので
static gData_t iniData;
gData_t data;
と定義しておいて
data = iniData;
のように初期化する方法も(一応)あります。


2.データの代入

info_t *infoData[100] は構造体の配...続きを読む

Q関数の引数をvoid*でキャストする

最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。
例えば、
func ( (void*) p );
こういうことです。

私の知っている知識では、
void* と 任意の型のポインタは キャストなしに相互に代入可能です。

関数の引数でも、キャストは要らないものだと思っていました。
そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・
違うのでしょうか。処理系によるとか。

逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。

下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。

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

void byte_order(void *vp)
{
char char_array[4];
strncpy(char_array, vp, 4);
printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]);
}

int main(void)
{
int a = 0x12345678;
byte_order(&a);

return 0;
}

このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。
また、C言語の質問であって、C++ではありません。

最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。
例えば、
func ( (void*) p );
こういうことです。

私の知っている知識では、
void* と 任意の型のポインタは キャストなしに相互に代入可能です。

関数の引数でも、キャストは要らないものだと思っていました。
そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・
違うのでしょうか。処理系によるとか。

逆に、関数の引数の型がchar*...続きを読む

Aベストアンサー

>私の知っている知識では、
>void* と 任意の型のポインタは キャストなしに相互に代入可能です。

そのとおりです。
キャストの必要はありません。
あってもなくてもかまいません。


>関数の引数でも、キャストは要らないものだと思っていました。
>そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・
>違うのでしょうか。処理系によるとか。

明示的に”void*にしているよ!”ということを示したい場合などに私はよく書きます。
まぁ、書いても書かなくても一緒ってことですけど。

>逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。

こちらに関しては、Cではエラーは出ませんが、C++ではエラーになります。

Q構造体の初期化のmemsetの第三引数

memset(&lvitem, 0, sizeof(LVITEM));
memset(&lvitem, 0, sizeof(lvitem));
LVITEMに特化した質問ではなく構造体の初期化について、この2つの書き方によるソース管理やコンパイルでのメリットとデメリットを教えてください。

Aベストアンサー

(1)memset(&lvitem, 0, sizeof(LVITEM));
この書き方は、構造体LVITEMを初期化しているんだな、と分かりやすい。
(2)memset(&lvitem, 0, sizeof(lvitem));
この書き方はとにかく変数lvitemを初期化するんだな、という感じだが、型が分からないので宣言しているところを参照しなければならない。
それともう一つ、ただ単に何回も初期化するんでなければ、こういう書き方もできる。
(3)LVITEM lvitem = {0};

結局どれがいいのかといえば、個人的にはケースバイケースですねえ。初期化を1回すればいいような感じなら(3)、構造体名を明示した方が調べる手間がなくなるようなら(1)、そうでなければ(2)を使います。
コンパイルでのメリット、デメリットは特にないんじゃないかなあ。アセンブラがまだ全盛だった頃ならともかく、いまじゃどのコンパイラだって最適化オプションで同じようなコードはくでしょう。
気にするほどでもないと思うけど…

QDWORDの実際の型は何でしょうか

VC++.NETの環境です。
DOWRD dw1 = 1;
int i = 2; と定義し
ここで
if ( i > dw1 ){
何かの処理;
}
とコーディングすると
warning C4018: '>' : signed と unsigned の数値を比較しようとしました。
のワーニングがでます。
これは、DWORDがint型でなくunsigned int型のようにも見えます。
ある本によれば(VC++.V.NET逆引き大全500の極意)
DWORD はint型であると記述されています。
もし、int型ならこのワーニングはでないはずなのですが、
なぜでるのでしょうか。又、DWORDの実際の型は何なのでしょうか。ご存じのかたおりましたら、教えていただけませんでしょうか。

Aベストアンサー

型定義が知りたいのならば、宣言ファイルを見れば疑問を挟む余地もありません。
DWORD型はwindef.hで
"typedef unsigned long DWORD;"
と宣言されています。

Visual Studioを使っているのならば、知りたい型の上にマウスポインタを置いて右クリック、ポップアップメニューの「定義へ移動」または「宣言へ移動」で簡単に知ることが出来ます。

Q構造体の初期化方法について

こんばんわ。
何度も申し訳ありません。

VC++.NET 2003を用いてコンソールプログラミングを行っています。前回この掲示板を利用して複数回実行するプログラムを作成し、そこに構造体を用いたプログラムを作成しました。以下に概要を示します。

グローバルで構造体を宣言しているため、複数回実行を行うプログラムでは前回の値が格納されたままであると思い、毎回実行時に構造体の初期化を行いたいと思っています。

そこで、以下に示します構造体の初期化はどのように記述すればよいのでしょうか?0で初期化したいと思っています。

よろしくお願い致します。

#define MAX 2000
//グローバル
struct tag{
int Npkt;
int gettime;
int rPkt;
int lossPkt;
}rdata[MAX];

main(){
  //for文で複数回実行処理
  for(i=0;i<=5;i++){
  //ここで構造体の初期化を記述する
//例として、5回プログラムを実行する
  }
}

こんばんわ。
何度も申し訳ありません。

VC++.NET 2003を用いてコンソールプログラミングを行っています。前回この掲示板を利用して複数回実行するプログラムを作成し、そこに構造体を用いたプログラムを作成しました。以下に概要を示します。

グローバルで構造体を宣言しているため、複数回実行を行うプログラムでは前回の値が格納されたままであると思い、毎回実行時に構造体の初期化を行いたいと思っています。

そこで、以下に示します構造体の初期化はどのように記述すればよいのでしょうか?0で初...続きを読む

Aベストアンサー

★まとめ
・既に『memset』関数や、『ZeroMemory』関数の回答があるので構造体の全体、1部の
 初期化の記述例を紹介します。
・それと『#include <memory.h>』を記述しないとメモリ関係の関数が利用できません。
 『ZeroMemory』関数の場合は『#include <windows.h>』があればそのまま利用できます。

●構造体全体を初期化
ZeroMemory( rdata, sizeof(rdata) ); または、
memset( rdata, 0, sizeof(rdata) ); です。

●構造体一部を初期化
ZeroMemory( &rdata[i], sizeof(struct tag) ); または、
memset( &rdata[i], 0, sizeof(struct tag) ); です。
※rdata[i]の1データだけ初期化します。

余談:
・『ZeroMemory』関数は Win32 API と分類されていますが、実体は『memset』関数に
 『#define』されているだけです。でも、戻り値を『VOID』型にキャストされているので
 『memset』関数のリターン値を取得できません。→第一引数のアドレスが『memset』関数
 ではリターンします。
・以上。おわり。

参考URL:http://taka.no32.tk/tips/Win32/ZeroMemory.html

★まとめ
・既に『memset』関数や、『ZeroMemory』関数の回答があるので構造体の全体、1部の
 初期化の記述例を紹介します。
・それと『#include <memory.h>』を記述しないとメモリ関係の関数が利用できません。
 『ZeroMemory』関数の場合は『#include <windows.h>』があればそのまま利用できます。

●構造体全体を初期化
ZeroMemory( rdata, sizeof(rdata) ); または、
memset( rdata, 0, sizeof(rdata) ); です。

●構造体一部を初期化
ZeroMemory( &rdata[i], sizeof(struct tag) ); または、
m...続きを読む

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

QC言語にて構造体のメンバが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);

}

C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成しています。
一応目的の動作はするのですが、プログラミングとして正しいか教えて頂ければと
思います。

<test.c>

int main()
{
/* ---------------------------------------- */
/* 構造体のメンバ(NULL保障無し)がNULLか */
/* 比較するサンプル */
/* ---------------------------------------- */

char buf[50];
/* サンプル構造体 */
struct ST_test {
int cd;
...続きを読む

Aベストアンサー

1)先頭が'\0'でない文字列をmemcpy()したのだから、*st_test.nameは'\0'でないのに
  決まっている。そもそも'\0'との一致判定をすることに意味があるのかどうか。
2)標準関数のプロトタイプ宣言を行なっているヘッダーファイルをインクルードしていない。
3)&buf[0]はbufと省略できる点を理解しているかどうか。
4)memcpy()で、文字列終端を含めて11バイトのデータを10バイトの領域にコピーしている。
  プログラムの仕様として正しいかどうか。
5)#1さんの回答のとおり、NULLと'\0'との違いをじゅうぶん理解できているかどうか。


人気Q&Aランキング