65. SWAPマクロ
意義
● 2数を交換する関数は、以下のようになります
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp
}
● 使用例:
int a = 10, b = 20;
swap(&a, &b);
● こんな単純な関数を、呼び出すのはもったい
ないですね
65
66. SWAPマクロ
意義
● 2数を交換する関数は、以下のようになります
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp
}
●
使用例:
int a = 10, b = 20;
swap(&a, &b);
●
こんな単純な関数を、呼び出すのはもったいな
いですね
●
マクロで書きましょう!
66
67. SWAPマクロ
基本形
● 一番オーソドックスなSWAPマクロです
#define SWAP(type, a, b)
{
type __tmp_swap_var__ = (a);
(a) = (b);
(b) = __tmp_swap_var__;
}
● 使用例:
int a = 10, b = 20;
SWAP(int, a, b);
67
68. SWAPマクロ
基本形:問題点
● 関数呼び出しのように使えません
– 関数呼び出しだと、アドレスを渡す必要がありま
した
● 複文に置き換えられるので、セミコロンを記
述する必要がないです
– でも、SWAP(int, a, b);と書いても問題ないです
● 以下のような、中括弧省略のif ~ else節におい
て問題があります
// コンパイルエラーとなる
if (a == 10)
SWAP(int, a, b);
else
SWAP(int, a, c);
68
70. SWAPマクロ
基本形:改善
● 以下が改善したものとなります
#define SWAP(type, a, b)
do {
type __tmp_swap_var__ = *(a);
*(a) = *(b);
*(b) = __tmp_swap_var__;
} while (0)
● 型を指定する必要があるので、完全にシーム
レスとは言い切れませんが...。
● 使用例:
int a = 10, b = 20;
SWAP(int, &a, &b);
70
91. ダフのデバイス
関数マクロへの応用
● 以下の<処理>の部分に、行いたい処理が来る
とよいですよね
void duff_memcpy(int *to, const int *from, int size) {
int n = (size + 7) >> 3;
switch (size & 7) {
case 0: do { <処理>;
case 7: <処理>;
case 6: <処理>;
case 5: <処理>;
case 4: <処理>;
case 3: <処理>;
case 2: <処理>;
case 1: <処理>;
} while (--n);
}
}
91
92. ダフのデバイス
関数マクロへの応用
● ダフのデバイスをマクロ化すると、以下のよ
うになります
– STATEMENT:行いたい処理(式または複文)
– __VA_ARGS__:次のステップ前の処理(省略化)
#define DUFFS_LOOP(n, STATEMENT, ...)
{
register int __tmp_loop_var__ = ((n) + 7) >> 3;
switch ((n) & 7) {
case 0: do { STATEMENT; __VA_ARGS__;
case 7: STATEMENT; __VA_ARGS__;
case 6: STATEMENT; __VA_ARGS__;
case 5: STATEMENT; __VA_ARGS__;
case 4: STATEMENT; __VA_ARGS__;
case 3: STATEMENT; __VA_ARGS__;
case 2: STATEMENT; __VA_ARGS__;
case 1: STATEMENT; __VA_ARGS__;
} while (--__tmp_loop_var__);
} 92
}