• 締切済み

可変長引数関数のマクロ関数について

可変長引数をとる関数をマクロで置き換えたいのですが、 この方法だとできません。うまく実現できないでしょうか? ------------------------------------------------------- #define TRACE(arg, ...) trace(__FILE__,__LINE__,arg, ...) void trace(char *file, int line, char *arg, ...) {   ...(略)... } func() {   ...   TRACE("hello %s", "taro");   ... } ------------------------------------------------------- よくあるトレース処理だと思いますがこんな感じです。 他にも代替手段は考えつきますが、 可変長引数の関数のマクロが可能かが知りたいです。 どなたがご存知の方がいらっしゃいましたら、よろしくお願いします。

みんなの回答

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

> 可変長引数をとる関数をマクロで置き換えたい いわゆる「一般的なC言語」では、できません。ただ、つい最近 C言語の 規格が新しくなりました(C99)。 その規格では、可変長引数を取るマクロが使えます。こんな感じ。 #define TRACE(fmt, ...) trace(__FILE__,__LINE__,fmt,__VA_ARGS__) void trace(char* file, int line, char* fmt, ...) 古い規格のCでtraceの活殺をしたければ、trace関数内を #ifdef ~ #endif で 括るしかないです。 void trace(char* file, int line, char* fmt, ...) { #ifdef DEBUG   ... #endif } 実行環境や使い方にもよりますが、関数呼出しのオーバーヘッドをそれほど 気にする必要はありませんよ。以下のような感じでも十分実用的です。 void trace(char* file, int line, char* fmt, ...) {   if (デバッグ出力をしない?) return;   ... (以下、デバッグ出力) } で、直接 trace をプログラムでは使う。

関連するQ&A

  • 可変長引数をもつオーバライド関数について

    オーバライド関数について質問があります。 以下のようなクラスAとBがあります。 クラスAは基本クラスです。 クラスBはクラスAから導出しました。 ------------------------------------ CLASS A { public: virtual void func(char* p, ...); } ------------------------------------ CLASS B : public A { public: void func(char* p, ...); } ------------------------------------ メンバ関数の func() はオーバライド関数で、可変長の引数を持っています。 今、クラスBの func() の中で、クラスAの func() をコールするようにコーディングしました。 ----------------------------------- void B::func(char* p, ...) { : : A::func( ???? ) : : } ----------------------------------- ところが、クラスBの func()が受け取った引数を、そのままクラスAの func() に渡したいのですが、どうしたらいいのか分かりません。これって無理でしょうか? 教えて下さい。

  • C言語での関数形式マクロの使い方

    前の質問No.300834(関数形式マクロと空白の質問)と関連します。 関数形式マクロで、引数として入れるものは、変数でなくて型名でも構わないのでしょうか。 例えば、 #define mymul(t,x,y) ((t)(x)*(t)(y)) と定義すると、 mymul(int, 5.0, 3.5) と呼び出すと、 ((int)(5.0)*(int)(3.5)) に置き換える、 (intでキャストした 5.0 と、intでキャストした 3.5 をかける) というのは可能でしょうか。 あと、関数形式マクロの呼び出しは、実行部分でなくてもよいのでしょうか。関数頭部(関数の本体の前の部分)で呼び出せますか。 例えば #define ARGUMENT3(t1,v1,t2,v2,t3,v3) ¥ (t1 v1, t2 v2, t3 v3) #define a_func b_func ARGUMENT3 と定義しておいて、 関数を定義するときに、 int a_func(int,x, char*,cp, int**,ypp) { ・・・・ } こんなことをすると、 int b_func(int x, char *cp, int **ypp) { ・・・・ } に置き換わりますか? もし、ARGUMENT3の定義を、ARGUMENT3の後の括弧の中のカンマのつけ方を変えて、 #define ARGUMENT3(t1 v1,t2 v2,t3 v3) ¥ (t1 v1, t2 v2, t3 v3) とし、 int a_func(int x, char* cp, int** ypp) { ・・・・ } こうすると、先ほどのようなb_funcの関数頭部に変換することは出来ませんか? (関数形式マクロでこのような空白の入れ方をしてよいのでしょうか。)

  • 可変個引数を使った関数で文字の長さを知りたい

    可変個引数を使った引数を使って引数の文字列の長さを知りたいのですがどうすればいいのかわかりません。 DXライブラリを使って文字列の長さを測って文字をどこにおくのかを決めているため文字列の長さがわからないと困ってしまいます。 どのようにすれば可変個引数を使った引数の文字列の長さを測れますか? 大体以下のような感じで作っています。 void kai( int *x , int *y ); //文字列を改行する関数 int JC( unsigned char code ); //文字が1バイト文字 か 2バイト文字か判別する void mozi_show2( int x , int y , int xm , int yb , int color , int char_set , const char *s , ... ){   int i = 0;   int xs = 0 , ys = 0;   int m_color = color;   char One[ 2 ]; //1バイト文字格納用   char Two[ 3 ]; //2バイト文字格納用   const char* p;   va_list args;   va_start( args , s );   p = s;   while( *p != '\0' ){     switch( *p ){       case '%':         p++;         assert( *p != '\0' );         switch( *p ){           case 'd':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%d" , va_arg( args , int ) );             //purintfと使い方はほぼ同じで左から文字を表示したいX座標・文字を表示したいY座標             //文字の色・文字の書式・格納用文字列・表示したいint型の数値をあらわしています             xs += 16;             /*             xs += GetDrawFormatStringWidthToHandle( char_set , "%d" , va_arg( args , int ) );             本来ならこの関数を使って文字列の長さを計る左から             文字列の書式・格納用文字列・長さを測りたいint型文字列             これを使うと別のものを計っているみたいで文字の長さがわからない             文字の長さってどうやって計るの?             */             break;           case 'f':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%f" , va_arg( args , double ) );             break;           case 'c':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%c" , va_arg( args , char ) );             break;           case 's':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%s" , va_arg( args , const char* ) );             break;           case '%':             DrawFormatStringToHandle( x + xs , y + ys * yb , m_color , char_set , "%%" );             xs += GetDrawStringWidthToHandle( "%" , 1 , char_set );             break;         }         p++;         break;       default:         if( JC( *p ) ){           Two[ 0 ] = *p;           Two[ 1 ] = *( p + 1 );           Two[ 2 ] = '\0';           DrawStringToHandle( x + xs , y + ys * yb , Two , m_color , char_set );           xs += GetDrawStringWidthToHandle( Two , 2 , char_set );           p += 2;         }         else{           One[ 0 ] = *p;           One[ 1 ] = '\0';           DrawStringToHandle( x + xs , y + ys * yb , One , m_color , char_set );           xs += GetDrawStringWidthToHandle( One , 1 , char_set );           p++;         }         break;     }     if( xs > xm ){       kai( &xs , &ys );     }   }   va_end( args ); } void zitu_draw( void ){   char *str = "%d個 OK";   int i = 12;   mozi_show2( 100 , 100 , 300 , 15 , red_s , MG_14_0 , str , i );   //左から 文字を表示するX座標・文字を表示するY座標・文字を改行する文字列の長さ   //改行した時のY座標の縦幅・文字色・文字の書式・表示したい文字列・%dに表示したいint型の値 }

  • 関数をの引数について。

    以下のように、関数を呼び出すときに引数の個数を可変にするスマートなやり方は、何かあるでしょうか? $arrは配列 func1($arr) { // $arrの個数が3個のとき func2($arr[0], $arr[1], $arr[2]); // $arrの個数が5個のとき func2($arr[0], $arr[1], $arr[2], $arr[3], $arr[4]); } 例えば、 $args = '$arr[0], $arr[1], $arr[2]' としたとき、 func2($args) とすると、func2には文字列として渡りますが、これを上のように func2($arr[0], $arr[1], $arr[2]) として呼びたいです。 こんな方法何かあるでしょうか? よろしくお願いします。

    • ベストアンサー
    • PHP
  • jQueryでの、引数を取るJS関数の呼出方法

    jQueryの学習をしています。 HTML & JavaScriptで下記のように書かれているコード <input type=button id=button1 onclick=func_a() /> <script> function func1(){ //処理いろいろ } </script> は、jQueryを使って書くと、 $('#button1').live('click', func_a); このように書けます。 <input type=button id=button1 onclick=func_b(arg1, arg2) /> <script> function func_b(argument1, argument2){ //処理いろいろ } のように引数を取る関数は jQueryではどのように書けばよいのでしょうか? $('#button1').live('click', func_b(arg1, arg2)); とは書けなかったので、今は、 if (arg1 == xxx){ $('#button1').live('click', func_b_1_1); } else { $('#button1').live('click', func_b_1_2); } などのように引数別に同じような関数を創って書いています。 DRY原則という同じコードを二度書くなという約束もあるようなので、 きっといい方法があると思うのですが、 お詳しい方、教えていただけるとうれしいです。 どうぞ、よろしくお願いいたします。

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

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

  • 配列の中身を順番に可変長定義関数に渡すには

    好きなだけ引数が渡せる関数があり、その引数に任意の配列の中身をeval関数を使わずに一つずつ渡したいのですが、どうすればいいのでしょうか。eval関数を使った場合は以下のような感じです。 $list=array("apple","banana","orange"); function hoge(){ print_r(func_get_args()); } $arg=implode ('","',$list); eval('hoge("'.$arg.'");');//hoge("apple","banana","orange"); よろしくお願いいたします。

    • 締切済み
    • PHP
  • 可変長引数関数の引数の文字列サイズを取得したい

    以下のような可変長の文字列を受け取れる関数があったとします。 ...の部分で引数を受け取ることが可能ですが、この場合引数の文字列サイズを 知ることは可能なのでしょうか? 関数を呼び出してみて例を挙げるとするなら、  GetArgs( "%s", "あいうえお" ); この「あいうえお」の部分の文字数をGetArgs内で知りたいのです。 void GetArgs( char * FormatString, ... ) {   va_list VaList;   va_start( VaList, FormatString );   // ここでFormatStringの引数の文字列サイズを取得したい   va_end( VaList ); }

  • 引数の可変

    覚えたての引数の可変を使ってみた素人であります。(独学です 見よう見真似で書いた為、目茶苦茶だと思われます。 自分で簡単なexeファイルを作ってみていて 引数の可変が必要となったので付け足そうとしていたのですが、「引数の可変」部の他 意外にもfor文からもエラーが出ました(while使えば済む話なのですが) 今までfor文をあまり使わずwhile文ばかり使っていた為、for文の基本的な構文が失敗しているのかもしれません。折角だから使ってみようとした結果がこれです。 #include <stdio.h> #include <locale.h> #include "DxLib.h" #include <string.h> #include <stdarg.h> int i; ・・・略・・・ class CharsOut{ ____int ypixel; ____char *hangar; ____int size; ____int HowMany; ____int list; public:   ____int CharsOuting(int HowMany,int ypixel,int size,...); }; int CharsOuting(int HowMany,int ypixel,int size,...){ ____va_start(list,HowMany); ____for (i=0;i<HowMany;i++){ ________printf("%s",va_arg(list,char *)); ____} ____va_end(list); ____return 0; } ypixel、size...といった変数等は気にしないでください。 成功していたらコードを足すつもりでした。 自分がやりたいことは、main関数から変数HowMany,*hangar等を受け取り 文字列*hangarを引数の分出力したいのであります。引数の可変は*hangarを何個か渡すつもりだったので使用しました。 こんな感じに使うつもりでしたc.CharsOuting(2,0,32,"I am ", "hangury"); ※リストは(int HowMany,int ypixel,int size,...)です ※ハングリーのスペルが違う等ということはとてつもなくどうでもいいことなのです。 自分で「main関数から*hangarを受け取り」と書いておきながらリストに*hangarがない時点でおかしいと思ってはいるのですが、記述の方法が分からないので書けません。 以下エラー (名前とか一部改変・不要な部分省略 1>------ ビルド開始: プロジェクト:(≡ω≡.), 構成: Debug Win32 ------ 1>コンパイルしています... 1>soucer.cpp 1>error C2040: 'i' : 'int' は 'int [5]' と間接操作のレベルが異なります。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2440: '=' : 'int' から 'int [5]' に変換できません。 1>配列型への変換はありませんが、参照またはポインタから配列への変換があります。 1>error C2446: '<' : 'int' 型から 'int *' 型への変換ができません。 1>整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。 1>error C2040: '<' : 'int [5]' は 'int' と間接操作のレベルが異なります。 1>error C2105: '++' には左辺値が必要です。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2065: 'list' : 定義されていない識別子です。 1>ビルドログは "file://c:\・・・\Debug\BuildLog.htm" に保存されました。 1>(≡ω≡.) - エラー 8、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== 文章能力なくて申し訳ありません。 ご回答頂ければ幸いであります。宜しくお願いします。 OS:WinXP コンパイラ:Visual C++

  • 引数をつけたマクロ定義とは

    引数つきマクロ宣言って、どういった場面で使うのでしょうか? 例えば #define abc(a) a*a と定義している場合 x=abc(a) のabc(a)がa*aに変わる。 でも、こんなことしたら abc(a)関数を呼び出せなくなるのでは? 要するに、「引数つきのマクロ定義が ある理由などを、説明していただければと思います。

専門家に質問してみよう