• 締切済み

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のように引数でダブルポインタを使用するケースは一般的なのでしょうか? 教えていただけるとうれしいです。 よろしくお願い致します。

みんなの回答

  • opera-man
  • ベストアンサー率26% (111/414)
回答No.6

>GetBuf(&x.tempAddr, (size_t*)&x.bufSize ); size_t*のキャストはポインタのため、スタックを壊すことはないですが、 型サイズがint<size_tでデータサイズ>intの場合は構造体が壊れます。。 GetBuf()関数は、エリアを動的に確保する関数かと思われますが、 このような用途の関数は必ずダブルポインタを使います。 それ以外に受け渡しようがないので(グローバル変数除く)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

キャストすれば, 確かに「構造体に直接代入」できます. ただし「プログラムが正常に動作しない」可能性と引き換え, ですが. たとえば sizeof(int) = 4 sizeof(size_t) = 8 という環境で, 正常に動作すると思いますか?

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

>GetBuf(&x.tempAddr, (size_t*)&x.bufSize ); 第2引数はダメです。 intとsize_tは違いますよ。

shin06ag
質問者

お礼

回答ありがとうございます。 Castすれば構造体に直接代入できると思っていました。。。 No1の回答者のように、 一度、同じ型の変数に代入するしか方法はないのでしょうか? char *address; size_t dataSize; test_t x; int ret; ret = GetBuf(&address, &dataSize); if (ret == 1) { x.tempAddr = address; } else { /* 略 */ }

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

typedef struct Test_t{ char* tempAddr; /* 先頭アドレスを格納 */ int bufSize; /* サイズを格納 */ } test_t; と GetBuf ( char ** address, size_t *dataSize ); に対して GetBuf(&x.tempAddr, (size_t*)&x.bufSize ); はダメです.

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.2

>このAPIのように引数でダブルポインタを使用するケースは一般的なのでしょうか? ダブルポインタなどと言うおかしな言葉を使わないで考えた方が良いでしょう。 「引数で値を返したいときは、引数では、"返したい値の型のポインタ"を使う」 というのは考えるまでもなく明らかなことですね。 従って、返したい型がポインタなら、引数はポインタのポインタになるのも同じく当然です。 >引数に構造体を直接指定する場合は、以下のようにしても問題ないでしょうか? 問題ありません。

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

char *address; size_t dataSize; test_t x; int ret; ret = GetBuf(&address, &dataSize); if (ret == 1) { x.tempAddr = address; } else { /* 略 */ } > このAPIのように引数でダブルポインタを使用するケースは一般的なのでしょうか? 珍しいことではないと思います。

shin06ag
質問者

お礼

回答ありがとうございました。 引数に構造体を直接指定する場合は、以下のようにしても 問題ないでしょうか? test_t x; GetBuf(&x.tempAddr, (size_t*)&x.bufSize );

関連するQ&A

  • C言語のvoid型ポインタ変数について。

    C言語のvoid型ポインタ変数について。 C言語のvoid型ポインタ変数について質問があります。 組み込み系の開発を行っているのですが、現在使用しているシステムで、 提供されている "API" を介してアプリケーション部のソフト作成を行っています。 この "API" ですが、引数の多くはvoid型ポインタとなっています。 ある人がこの引数がvoid型となっているのを見て、 『なんでvoid型なんや??、C言語でアセンブラと違うんやから、void型なんかにしない方が良い』 とおっしゃいました。 この意味がよくわからなかったのですが、なぜ void型はよろしくないんでしょうか? -- 僕が思うに、APIなんやから引数を void型ポインタ にすることでどんな型にも対応できる 汎用的であると感じ、逆にこの方が良いのではと感じたのですが。。 -API例---- int _exApiKannsuu( char in_data, void* out_data ) "in_data" をもとに "out_data" を取得する。 どーやらこの "out_data" が void型 であるのががよくないらしい・・

  • C言語での関数の引数の受け渡しについて

    C言語での関数の引数の受け渡しについて教えてもらいたいのです。 char *p=Goo;  というポインタpがmain関数で定義され、このポインタpをある関数 void func(・・・) に渡すことは出来ますか? つまりポインタを実引数として扱うことはできるのかという事ですが・・・ int p=10; とかだったら、 void func(int test) の関数には、main関数で func(p) で仮引数testにわたせると思うんですが・・・ もし出来るようでしたら、関数の渡し方と定義の記述を教えてください。 どうか宜しくお願いします。

  • ポインタのサイズ

    ポインタのサイズは、 int型のポインタでも、char型のポインタでも、 doubleのポインタでも、構造体のポインタでも、 全部サイズは4バイトです。 というのを見かけましたが、ほんとうですか? 教えてください。

  • ポインタの引数について。

    C言語初心者です。 既存のプログラムを直そうとしているのですが、ポインタの概念がいまいち理解できていないのか、修正した箇所がうまく動きません。 どうすればよいかをご教示いただけませんでしょうか。 元のプログラムは void sub() { SOCKET s; struct msg r_msg; int time; int cc; cc = sub_recv(s, &r_msg, time); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } という感じでr_msg構造体にrecvで受け取ったものを入れて行きます。 ccにはrecv()の戻り値でサイズが返ってきて直後のifにはひっかかりません。 構造体の中でサイズが固定されているため、可変にするために以下のようにしたいです。 extern int buflen; void sub() { SOCKET s; unsigned char *r_msg; int time; int cc; r_msg=(char *)malloc(sizeof(char)*buflen ); cc = sub_recv(s, r_msg, time); free(r_msg); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg /*ここの代入は無意味と思いますがなくしても同様の結果のなので残してます。*/ cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } しかし、このような修正で*r_msgにはrecv()で受け取った内容が入る気がするのですが、 ccには-1が入ってしまい、ifに引っかかって終了してしまいます。 この時のerrnoを見ても104が入り、connection reset by peerといった感じです。 recv()の第二引数にはこれがバッファが用意されてればいいと解釈しておりますが、 これではバッファが1バイトしかとれていないなどあるのでしょうか。 因に、send()がないからというのはありません。 キャストが間違えているなどもあるかもしれませんが、宜しくお願いします。

  • 構造体とポインタ配列

    現在C言語の勉強をしております。 環境はwindowsXP、コンパイラはVC6.0です。 構造体と、ポインタの配列についてなのですが、 以下のような構造体が宣言されている時に、リスト構造にデータがいくつか入っているとします。 // 構造体 typedef struct address { unsigned char names[NAME_SIZE+1]; /* 名前 */ char tels[TEL_SIZE + 1]; /* 電話番号 */ struct address *prev; /* 前へのポインタ */ struct address *next; /* 次へのポインタ */ }Address, *a_pt; そのリスト構造を先頭要素か順番にポインタ配列に格納するには以下の方法ではおかしいでしょうか? /* ポインタ配列を用意する */ Address *array[MAX_COUNT]; /* top_ptは先頭のポインタです */ pt = top_pt; /* データがなくなるまで配列へ格納する */ while(pt != NULL){ array[count++] = pt; pt = pt->next; } /* 配列の最後はNULLとする */ array[count] = NULL; また、配列の中身を確認する方法としては、 printf("配列の中身:%s\n", array[0]->names); では、アドレスが表示されてしまうのかな・・と思ったら、accessViolationで落ちてしまいました・・・。 中身はどうしたらデバッグ出来ますでしょうか? そもそも、以下の2つは何か違いはありますか? Address *ptA[100]; a_pt ptB[100]; 皆さん、どうかよろしくお願いいたします。 理解不能な場合はご指摘ください。

  • 【C言語】引数にファイルパスを送りたい

    DLLで外部のファイルサイズを得る関数を作っています。 C言語は書きながら覚えていこうとしているのですが、 どうしても分からない点がありました。 ソースをここに正しく書ける自信がないので日本語を含めて大体で書きます。 いろいろなサイトのコピペです。 double __stdcall filesize(){ HANDLE hFile; DWORD size; hFile = CreateFile( _T(絶対パス, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); size = GetFileSize( hFile, NULL ); CloseHandle( hFile ); return(size); } このような感じで書いていて最後にretuenでファイルサイズを正しく得ることができました。 この絶対パスは環境によって変わるので引数にしようと考えました。 そしてfilesize()の中にどのように記述すればいいかで躓いています。 filesize(絶対パス){ char pass[] = "絶対パス"; hFile = CreateFile( _T(pass, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); こんな感じで書ければいいのですがC言語はポインタや文字列の扱いが難しいですね。 初歩的なことで申し訳ありませんがよろしくお願いします。

  • ポインタのポインタを引数にもった関数から値を得たい

    すいません。 似たような題も多かったのですが、初心者のため、わかりませんでした。 質問させてください。  ポインタのポインタを引数にもった関数を作りたいのですが、まったくわかりません。 (ポインタであれば、何とかできたのですが…) 例を作ってみました。下記で、dd[2][2]にtest2関数から値を得るとします。 ?1と?2、?3に何を入れたらよいでしょうか?  (?1で得られる値は何でもかまいません。) きわめて抽象的で、申し訳ないのですが、どうぞよろしくお願い致します。 void test2(double **d1) { ?1 } void C_testDlg::OnBnClickedButton1() { // TODO: ここにコントロール通知ハンドラ コードを追加します。 double dd[2][2]; ?2 test2(?3); CString cs; cs.format("%g", dd[1][2]) ::AfxmessageBox(cs); }

  • 2次元配列とポインタの引数受け渡しについて

    2次元配列を関数に渡すときは、引数に渡す2次元配列と同じサイズを指定、もしくは2次元目のサイズのみ合わせて渡す方法がありますが、両方とも違うサイズで同じ関数を使いたいです。 最初は中身が同じで引数で受け取る2次元配列のサイズだけ、それぞれに合わせた引数を持つ関数を2つ作っていたのですが、なんだか冗長な気がしました。 そこで、2次元配列の先頭ポインタとサイズを受け取るようにすればいいのかと思い、テストとして次のプログラムを作成してみました。 #include <stdio.h> void func(unsigned char *a, int y, int x); int main(void) { unsigned char a[10][10]; func(a, 10, 10); printf("%d\n", a[7][4]); return 0; } void func(unsigned char *a, int y, int x) { int i, j; for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { *(a + i*y + j) = i * j; } } } もちろんこれでも動くのですが、やはりこういう書き方はルールにはないので、コンパイルで警告が出ます。 a.c: In function ‘main’: a.c:10: warning: passing argument 1 of ‘func’ from incompatible pointer type a.c:4: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[10]’ このような書き方はやはりやめたいいのでしょうか。 また、その際はサイズ別に関数を作るしかないのでしょうか。 他にいい方法があれば教えていただけると助かります。

  • C言語 ポインタ型引数の呼び出しについて2

    C言語 ポインタ型引数の呼び出しについて2 以前質問した関数ですが、ネットを検索していたら同じような引数の関数を見つけました。 多分これを参考にしたのではないかと思います。 char* GetCSV(char** pBuf) { char *p = *pBuf,*q = p; if (!p) return p; if (*p == '"') { *p++ = 0; do ++q; while (*q && *q != '"'); if (*q == '"') *q++ = 0; } if ((*pBuf = strpbrk(q,",")) != 0) *(*pBuf)++ = 0; return p; } 当方がやりたい処理はVB6でCSVをリードして処理しているのですが、処理速度が遅いため I/OをしているところをCに変更して処理速度が向上するか確認したいのです。 他にも色々調べたのですがstrtokを使って処理されている方が多いようなのですが、 "1,,2,3"と言うデータの場合に"1" "2" "3"と返ってくるようで、 私のほしい値としては"1" "" "2" "3"というように返ってきてほしいのです。 上記のGetCSVでは"1" "" "2" "3"に返ってくるようです。 何とか動くようにと下の関数をかぶして実行して見たところ結果は正しかったのですが どうもメモリリークをしているように思います(タスクマネージャーのメモリ使用量は増えていく) int split(char *ary[], char *s) {   int len = 0;   int lsize = 0; char *strBuff[BUF_SIZE]; *strBuff = strdup(s); lsize = strlen(*strBuff); for (len = 0; len < lsize; len++) { if ((ary[len] = GetCSV(strBuff)) == NULL) break; } free(*strBuff); return len; } strdupの後メモリを開放しているつもりなのですが問題あるのでしょうか? C言語をあまりしたことがないので詳し方ご教示願えないでしょうか?宜しくお願いします。

  • ポインタ

    字列2つを入力し,同じ文字列かどうかを判定するプログラム ポインタの操作で文字列の比較を実現する。 (ライブラリ関数 strcmp を仕様しない) 関数の中身が上手に実現出来ません。 文字列を指すポインタ変数 2 つを引数に取り,同じ文字列なら -1 を,異なる場合は先頭から一致した文字数 を返す関数 必ず,具体的な解答を提示して下さい。 char str__com(char *s,char *t,int count) { while(*s = *t != '\0'){ if(s != t){ return -1; } if(s == t){ count++; } {s++;t++;} } return -1; }

専門家に質問してみよう