- ベストアンサー
可変長引数を実現する va系
今、可変長引数をBUFFERにいれて 送る(SSLを使いますが・・・)ことをしていますが、 どうしてもその部分らしいところでwarningがでます。 どうもいまいちva系の取り扱いがわからないので、 アドバイスいただけるとうれしいです。 ****ソース(va系が含まれるところのみ)**** WriteToClient (fmt, va_alist) char *fmt; va_dcl { va_list ap; char * ssl_buf[1024]; va_start (ap); vfprintf (stdout, fmt, ap); va_end (ap); //SSL SSL_write(ssl, ssl_buf, sizeof(ssl_buf) ); } *****コンパイル後のwarningメッセージ**** /usr/local/lib/gcc-lib/i386-pc-solaris2.8/2.95.3/include/stdarg.h:96: warning: ` va_start' redefined /usr/local/lib/gcc-lib/i386-pc-solaris2.8/2.95.3/include/varargs.h:111: warning: this is the location of the previous definition SSLpasschanger.c:216: macro `va_start' used with just one arg わかる方いらっしゃいましたら、よろしくおねがいいたします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
ん~つまり WriteToClient 関数を printf のように扱いたいってことですか? それでしたら、こんな感じだと思います。 void WriteToClient(char* fmt, ...) { char ssl_buf[1024]; va_list ap; va_start(ap, fmt); vsprintf(ssl_buf, fmt, ap); SSL_write(ssl, ssl_buf, sizeof(ssl_buf)); } この書き方で良かったのかどうか忘れてしまいましたが、とりあえず ap には fmt の次の引数のアドレスが入るはずです。 ただ、va_ マクロの実装は処理系によってかなり違うと思いますから、やはり自信は無しです。 呼び出し方は printf と同じです。フォーマットも指定してください。 WriteToClient("%s", "500 Username required."); // "全角空白" でインデントしてますのでご注意を…もうご存知でしたね。 // No.1 で関数内に書いた ... は "省略" の意味です。なので 214 ... は必要ないです。引数リストの ... は必要です。 // それから gcc には va_alist や va_dcl というマクロもあったのですね。不勉強でした。No.1 の後半部分は忘れてください。
その他の回答 (3)
- route156
- ベストアンサー率85% (93/109)
すみません。書き忘れました。 warning メッセージについてですが、stdarg.h と varargs.h で定義が重複しているのではないでしょうか。普通はヘッダファイルの中で二重定義を避けるための記述がされているはずですが、とりあえずインクルードファイルは stdarg.h の方だけで試されてみると良いと思います。
お礼
丁寧な説明、ありがとうございます! すごく感動してます。 warningはきれいに消えました!(T▽T)うれし~♪ お手数ながら、その後のエラーのことも教えていただけないでしょうか? さっそく一番下に書いていただいたもの(↓)でやってみたのですが、 208 void WriteToClient(char* fmt, va_list va_dcl) 209 { 210 char ssl_buf[1024]; 211 212 vsprintf(ssl_buf, fmt, va_dcl); 213 SSL_write(ssl, ssl_buf, sizeof(ssl_buf)); 214 ... 215 } 関数を呼び出すとき、引数が少ないというメッセージが帰ってきました。 342:too few arguments to function `WriteToClient' 呼び出すときは、 342 WriteToClient ("500 Username required."); のように呼び出しているのですが・・・ printfと同じように記述すればよい、と思っていたのですが・・・ちがいますかね? どうしたらよいでしょうか? まだプログラミング初心者なもので・・・すいません(^-^; お願いします。
WriteToClient そのものが、可変引数関数になるのなら、 route156 さんの書かれた、function のように、 void WriteToClient(char *fmt, ...) とします。まぎらわしいのですが、2つ目の引数はドットを3つ連続で書いてください。
- route156
- ベストアンサー率85% (93/109)
うろ覚えで自信は無いのですが、va_start, va_arg, va_end は可変長引数を一つずつ取り出す場合に使ったと思います。 void function(char* fmt, ...) { va_list ap; int param1; char* param2; va_start(ap, fmt); param1 = va_arg(ap, int); param2 = va_arg(ap, char*); ... va_end(ap); } ただ、ご質問では vfprintf を使われているようですので、これは引数として va_list をそのまま受け取りますから、va_start 等は必要ないと思います。 void WriteToClient(char* fmt, va_list va_dcl) { ... vfprintf(stdout, fmt, va_dcl); ... } 老婆心ながら WriteToClient の引数を ssl_buf にセットするのでしたら、次のようになるのでは? 他の部分がわからないので推測ですが。 void WriteToClient(char* fmt, va_list va_dcl) { char ssl_buf[1024]; vsprintf(ssl_buf, fmt, va_dcl); SSL_write(ssl, ssl_buf, sizeof(ssl_buf)); ... } それから、スタック上のバッファを使う時は、オーバーフローに留意された方が良いと思います。 以上、確認はしていないので間違いがあるかもしれません。その点はお許しを。
お礼
御礼が遅れてしまってすいません。 おかげさまでなんとか無事できました。 ありがとうございました!!! とても感謝しております!