• 締切済み

関数マクロの書き方

#difine GET_INFO(data) \ do{\ char* addr = topaddr + sizeof(int);\ memcpy(&data,addr,sizeof(int)); \ while(0) 取得さきのメモリのデータ構造は typedef struct _data_t{ int data[2] }data_t data_t test; メモリ上のデータの先頭アドレスはtopaddrとなっている状態で test.data[1] の値を取得する関数マクロの定義としてGET_INFOの書き方は 間違っていますでしょうか?

みんなの回答

  • Tort_Capa
  • ベストアンサー率21% (19/88)
回答No.4

 実際に値が取得できるかどうかについては触れませんが、正しいマクロ定義の仕方は、 #define GET_INFO(data) \ do { \ /* 省略します。 */ \ } while(0) というように、「while(0)」の前に「}」が必要です。  マクロ定義にダミー的なdo { } while(0)を使うテクニックは、約20年程前に某雑誌で「きだ あきら」という方が日本国内向けに公表してしまったテクニックです。  do { } while(0)を使うメリットは、if文中においてelseより前方で呼び出すときに実感できます。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.3

そもそもint型同士の代入(でなけりゃdataがバッファオーバーフローでコケる)でmemcpy使う神経が理解できませぬ。

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

流行ってるんですか? 別の人(?)の似たような質問が続いてるんですが。 #difine → #define にして 使うときは GET_INFO(d) ; } while(0) ; という風にすれば、おそらく期待通りの動作をするでしょう。 見掛け上は、}が対応とれませんが、それはそれでソースの難読化に使えます。 これ、マクロで書く意義ってあるのでしょうか? memcpy呼びだしてるから効率化/高速化になってないし。 sizeof(d) == sizeof(int)の変数dに対してでないと、転送される領域が足りなかったり余ったりして、バグの元だし。 test.data[1]の値を取りたいなら d = test.data[1] ; でいいだろうし。 topaddr + sizeof(int)なんて環境や実装に依存する方法よりは、 ((data_t *)topaddr)->data[1] とかが確実だし。

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

エンディアンとか問題ない…んでしょうかね? とりあえず、その書き方だと大量のコンパイルエラーが出そうですが。 # doの後の「{」に対応する「}」が遙か彼方へ。

関連するQ&A

  • 構造体内のポインタのポインタについて

    ポインタを理解するために以下のようなテストプログラムを作りました。 test.h --- typedef struct i_info{ int i_id; char i_name[64]; } I_INFO; typedef struct j_info{ int j_id; char j_name[64]; } J_INFO; typedef struct k_info{ int k_id; char k_name[64]; } K_INFO; typedef struct info{ int id; char name[64]; I_INFO iinfo; J_INFO *jinfo; K_INFO **kinfo; } INFO; --- test.c --- 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include "./test.h" 4 5 int main(int argc, char **argv) 6 { 7 INFO info; 8 J_INFO j; 9 K_INFO k; 10 K_INFO *pk=NULL; 11 12 memset (&info,NULL,sizeof(info)); 13 memset (&j,NULL,sizeof(j)); 14 memset (&k,NULL,sizeof(k)); 15 16 info.id = 1; 17 memcpy(info.name,"***",3); 18 19 info.iinfo.i_id = 2; 20 memcpy(info.iinfo.i_name,"*i*",3); 21 22 info.jinfo = &j; 23 j.j_id = 3; 24 memcpy(j.j_name,"*j*",3); 25 26 info.kinfo = &pk; 27 pk= &k; 28 k.k_id = 4; 29 memcpy(k.k_name,"*k*",3); 30 31 printf( "%d\n",info.id); 32 printf( "%s\n",info.name); 33 printf( "%d\n",info.iinfo.i_id); 34 printf( "%s\n",info.iinfo.i_name); 35 printf( "%d\n",info.jinfo->j_id); 36 printf( "%s\n",info.jinfo->j_name); 37 /* 38 printf( "%d\n",info.kinfo->k_id); 39 printf( "%s\n",info.kinfo->k_name); 40 */ 41 } --- 38,39行目をコメントアウトするとコンパイルは通るのですが、 そのままだとコンパイルエラーになります。 なぜいけないのでしょうか?理由を教えてください。

  • 構造体のmemcpy書き込む

    struct{ char a; char b; } test01_t struct{ char c; char d[3]; } test02_t struct{ test01_t test01; test02_t test02; } 書き込み先の領域の先頭アドレス char* Addr; データ構造が以下になっている状態で、 struct{ test01_t test01; test02_t test02; } test01_t test01の領域には書き込まず test02_t test02の情報だけ 領域にmemcpyまたはその他の方法で書き込みむにはどうしたらよいでしょうか? よろしくお願い致します。

  • メモリ動的確保について

    こんにちはです。 メモリの動的確保なのですが、 typedef struct DATA{ char name[256]; char pass[256]; int money; }BANK; void insert(BANK *p,int max); int main(){ int i; size_t st; BANK *person; person = (struct DATA *)malloc(sizeof(struct DATA)); //person = (struct DATA *)malloc(5); if(person == NULL){ printf("確保失敗\n"); exit(-1); } //memset(person,'\0',sizeof(struct DATA)); と、言う風に、記載ソースは途中ですがメモリをとりました。 mallocの後ろの部分ですが、sizeof(struct DATA)と5ではどうちがうのでしょう??2通りともコンパイルエラーはないです。 5は動的に最大5までとるって事はわかるのですが、struct DATAの方はいくつとるのです??いくつもで入力次第です? そして、動的したのにたいしてmemsetしたら実行エラー(コンパイルは通りました)おきました。動的にたいしてmemはダメなのでしょうか? アドバイスいただけたらありがたいです。宜しくお願いいたします。

  • 値を返さないといけないのに、返さない関数の挙動

    こんな感じの構造体・関数を作ったとします。 typedef struct personal_info {    char name[10];    char address[20]; } personal_t; personal_t getPersonal(int id){;} これには2つのギモンがありまして 1.getPersonalの中は何もせず、値を返さないのに なぜか、コンパイルは通る 2.実行すると、正常に動く いったい、どういう事なのでしょうか。 不思議でたまりません。 どうぞよろしくお願いします。

  • 構造体の中でユーザー定義型の型を使いたい TurboC → VC++2005

    昔、TurboCで作ったソースをVC++2005に置き換えようと難儀しています。 以下、構造体の中でユーザー定義型の型を使いたいのですが、 方法がわからず困っています。 ソースは途中で、コンパイルエラーになりませんが、肝心な所は コメントになっています。 詳しい方、教えていただけますか? /* 昔の古い構造体を VC++2005で使いたいです。 typedef struct _Test1{ char key[128]; char val[10]; } Test1; typedef struct _Test2{ char key[128]; Test1 val[10]; } Test2; */ #include <memory.h> using namespace System; using namespace System::Runtime::InteropServices; // テンプレート?でcharやshort型の配列はできるみたいです。 template<typename TYPE, size_t size> [StructLayout(LayoutKind::Sequential, Size=sizeof(TYPE) * size)] public value struct native_array{ TYPE elem; property TYPE default[int] { TYPE get(int index) { pin_ptr<TYPE> p = &this->elem; return p[index]; } void set(int index, TYPE value) { pin_ptr<TYPE> p = &this->elem; p[index] = value; } } }; public ref struct Test1{ String^ key; native_array<char, 10> val; Test1(){ key = "test1だよ"; pin_ptr<char> p = &this->val.elem; array<char>^ data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; pin_ptr<char> dat = &data[0]; memcpy(p, dat, sizeof(this->val)); } }; public ref struct Test2{ String^ key; // charやshortなどでなく、ユーザー定義型のTest1の型を // 配列として10個確保したい // 記述方法がわかりません。 Test2(){ key = "test2だけど、test1の型を使いたいです。"; // 記述方法がわかりません。 } }; int main(array<String^>^ args){ Test1 test1; Test2 test2; // Test1 Console::WriteLine(test1.key); for (unsigned i = 0; i < sizeof(test1.val) / sizeof(test1.val[ 0 ]); ++i) { Console::WriteLine(test1.val[ i ].ToString()); } // Test2 Console::WriteLine(test2.key); // 記述方法がわかりません。 return 0; }

  • winsockを使った通信方法

    送信側 #include <winsock2.h> #include <string.h> int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; typedef struct recv { char Name[32]; int Flag; } RECV; RECV send; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); strcat(send.Name, "ABC"); send.Flag=12; len=sizeof(send); sendto(sock,(char *)&send,len, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); system("pause"); return 0; } 受信側 #include <stdio.h> #include <winsock2.h> #include <string.h> int main() { typedef struct rcv { char Name[32]; int Flag; } RECV; WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; RECV rcv; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); len=sizeof(rcv); recv(sock,(char *)&rcv, len, 0); printf("%s [%d]\n",rcv.Name,rcv.Flag); closesocket(sock); WSACleanup(); system("pause"); return 0; } winsockを使ったUDP通信プログラムで構造体データを送る事が出来ないのですが どこに誤りがあるのでしょうか? コンパイルは通ってるのですが、送信側を起動しても受信側で受け取ることが出来ていない状況です。

  • ポインタのサイズ

    ポインタのサイズがintと同じになるのは知っているのですが、 以下のコードの場合、 typedef struct hoge{ char buf1[8]; char buf2[16]; }HOGE; void test_func(HOGE *pHoge) { printf("型[%d],実際[%d]\r\n", sizeof(HOGE), sizeof(*pHoge)); memset(pHoge, 0x00, sizeof(*pHoge)); } 正しくサイズが取得できるのですが、 この使い方はC99の仕様的には正しいのでしょうか? よろしくお願いします。

  • C言語 ダブルポインタを引数にもつAPI

    GetBuf ( char ** address, size_t *dataSize ); 第1引数: バッファの先頭アドレスをかえす 第2引数: バッファサイズをByte単位で返す 戻り値 1:成功      -1 取得失敗 typedef struct Test_t{ char* tempAddr; /* 先頭アドレスを格納 */ int bufSize; /* サイズを格納 */ } test_t 上記のAPIから情報を取得し、以下の構造体にデータを保持しようとしていますが GetBuffのダブルポインタの情報を構造体のメンバtempAddrに格納するにはどうしたらよいでしょうか このAPIのように引数でダブルポインタを使用するケースは一般的なのでしょうか? 教えていただけるとうれしいです。 よろしくお願い致します。

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

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

  • UDP通信について

    UDP通信で困っています。 TCP/IP通信はすぐにうまくいったのですが、 UDPの簡単なサンプルがちゃんと動きません。 間違いがあればご指摘ください。 よろしくお願いします。 (クライアント側ソース int sock; struct sockaddr_in din; memset(&din, 0, sizeof(din)); din.sin_port = htons(50050); din.sin_family = AF_INET; din.sin_addr.s_addr = inet_addr("サーバーIP"); sock = socket(AF_INET, SOCK_DGRAM, 0); int buf = 12345; sendto(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&din,sizeof(struct sockaddr_in)); (サーバー側ソース int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(50050); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return(1); } struct sockaddr_in fromaddr; socklen_t len = sizeof(struct sockaddr_in); int buf; recvfrom(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&fromaddr,&len); printf("recv:%d\n",buf);

専門家に質問してみよう