プロが教える店舗&オフィスのセキュリティ対策術

前の質問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の関数頭部に変換することは出来ませんか?
(関数形式マクロでこのような空白の入れ方をしてよいのでしょうか。)

A 回答 (5件)

●#define mymul(t,x,y) ((t)(x)*(t)(y))


実際にコンパイルしてみれば分かりますが、これはOKです。期待通りにコンパイルされます。
No.1 の
> mymul(int(5.0),int(3.5))
の中にある「int(5.0)」という書式のキャストは、C++ではOKですが従来のCではコンパイルエラーになるので、注意してください。

●関数形式マクロの呼び出しは、実行部分でなくてもよいのでしょうか
関数形式かどうかに関わらず、マクロ式はどこにでも書けます。
要するにC++でいうところの「テンプレート関数」みたいなものをCで実現したいということですよね。もちろんこれも実現可能です。
> #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)
と展開されます。

ただ、マクロ引数は1つずつカンマで区切らなければならないので、
> ARGUMENT3の定義を~
> #define ARGUMENT3(t1 v1,t2 v2,t3 v3) ¥
> (t1 v1, t2 v2, t3 v3)
これはさすがにエラーとなります。
っていうか、これはもはや展開の意味ないですよね。
ARGUMENT3 の定義を消せば、期待通りにコンパイルされます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。わかりました。

No.1の
>#define mymul(x,y) (x*y)
>mymul(int(5.0),int(3.5))
>でOKです

を見たとき、私にはまったく意味がわかりませんでした。
 私がC++のことを知らないためのようですね。

>C++でいうところの「テンプレート関数」みたいなものをCで実現したいということですよね。

私はC++を知らないですし、テンプレート関数というものも知らないです。

質問の
>#define a_func b_func ARGUMENT3
>と定義しておいて、
>関数を定義するときに、
>int a_func(int,x, char*,cp, int**,ypp)
>{
>・・・・
>}
これは、たまたま手に入れたソースコードの書き方です。人が書いたものなので、本当の目的は不明です。私が思うに多分、関数の分離形式(古い形式)と一括形式(ANSI C の書き方)の違いを吸収するためではないか、と思います。(ソースコードが書かれたのも、かなり前なのかもしれません。)

他の目的は私には思い浮かびません。

次のような定義がどこかにあるのかもしれません。
#ifdef hogehoge
 #define ARGUMENT0( )   (void)
 #define ARGUMENT1(t1, v1)  (t1 v1)
 #define ARGUMENT2(t1, v1, t2, v2)  (t1 v1, t2 v2)
#else
 #define ARGUMENT0( )   ( )
 #define ARGUMENT1(t1, v1)  (v1) \
   t1 v1;
 #define ARGUMENT2(t1, v1, t2, v2)   (v1, v2) \
  t1 v1; \
  t2 v2;
#endif

もちろん、引数がもっとたくさんあるときにも対応できるように、ARGUMENT10くらいまで定義しておくんでしょう。

ご回答で、このソースコードの書き方に関しては、もうほとんど納得いきました。


なお、質問では、
>#define a_func b_func ARGUMENT3
と、a_func と b_func とでぜんぜん別のような名前がついていますが、
実際のソースでは、(命名規則があるらしく)似た名前になっています。

お礼日時:2002/06/27 23:09

leaz024さん


どうもすみませんでした
(ANSI Cで話をした方がよかったですね)
    • good
    • 0

> ところで、ターゲットのコンパイラは何でしょう?


私が確認に使用したのは「Borland C++ 5.5(Windows)」と「gcc(Linux)」です。
    • good
    • 0

コンパイラ依存でしたか


申し訳ありませんでした
(eaz024さん ありがとうございます)

ところで、ターゲットのコンパイラは何でしょう?
    • good
    • 0

コンパイル自体できませんよ



5.0*3.5を5*3で計算したいのですよね?

#define mymul(x,y) (x*y)
mymul(int(5.0),int(3.5))
でOKです

mymul(5.0,3.5)にすれば5.0*3.5です
(キャストがわかってますよね???)
(defineがわかってますよね???)

>関数形式マクロの呼び出しは、実行部分でなくてもよいのでしょうか。
実行部分とは何でしょうか?(例がよくわからないの、何をしたいのでしょうか?)
    • good
    • 0
この回答へのお礼

>実行部分とは何でしょうか?(例がよくわからないの、何をしたいのでしょうか?)

実行部分などという意味不明の言葉を使ってすみません。
宣言などに対して、演算子などを使って演算する部分のことを指すつもりで使いました。

手元の『新ANSI C言語辞典』という本の「文」という項に、次のような記述があります。

「FORTRANのように宣言を文の一種として捉え、「宣言文」とする考えもあるが、K&Rと規格では、文は「実行する動作を指定する」と規定しているため、宣言は文から外されている。」

そうすると、「実行」という言葉を使うのも、当たらずとも遠からず、といった感じだと思います。
厳密には「文」という表現になるんでしょうか。

いずれにしても、質問の後半の意図は、関数頭部で使えるのか、ということです。
これは回答No.2で解決しました。もう問題はありません。

(関数頭部という言葉は、手元の『明解C言語入門編 例解演習』(柴田望洋 著)という本で使われているので、大丈夫だと思います。)

お礼日時:2002/06/29 09:10

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