#define SQUARE(x) ((x)*(x))
int main() {
int x = 2;
int y = SQUARE(x++); // Undefined behavior even though it doesn't look
// like it here
return 0;
}
而:
int square(int x) {
return x * x;
}
int main() {
int x = 2;
int y = square(x++); // fine
return 0;
}
例二:
struct foo {
int bar;
};
#define GET_BAR(f) ((f)->bar)
int main() {
struct foo f;
int a = GET_BAR(&f); // fine
int b = GET_BAR(&a); // error, but the message won't make much sense unless you
// know what the macro does
return 0;
}
相比之下:
struct foo {
int bar;
};
int get_bar(struct foo *f) {
return f->bar;
}
int main() {
struct foo f;
int a = get_bar(&f); // fine
int b = get_bar(&a); // error, but compiler complains about passing int* where
// struct foo* should be given
return 0;
}
Finally, macros can be difficult to debug, producing weird syntax errors or runtime errors that you have to expand to understand (e.g. with gcc -E), because debuggers cannot step through macros, as in this example:
one drawback to macros is that debuggers read source code, which does not have expanded macros, so running a debugger in a macro is not necessarily useful. Needless to say, you cannot set a breakpoint inside a macro like you can with functions.
However answers here mostly explain the problems with macros, instead of having some simple view that macros are evil because silly accidents are possible. You can be aware of the pitfalls and learn to avoid them. Then use macros only when there is a good reason to.
当您想要操作调用程序局部作用域中的变量时,将指针传递给指针正常工作,但是在某些情况下使用宏仍然没有那么麻烦。< br > (assignments to multiple variables, for a per-pixel operations, is an example you might prefer a macro over a function... though it still depends a lot on the context, since inline functions may be an option).
不可否认,其中一些依赖于编译器扩展,而这些扩展并不是标准的 C 语言,这意味着您可能最终得到的可移植代码较少,或者必须将它们用 ifdef表示,所以它们只有在编译器支持的情况下才能得到利用。
具体例子: 您需要编写一个标准‘ strpbrk’函数的替代版本,它将接受一个(指向 a 的)函数,该函数将返回0,直到找到一个通过某些测试(用户定义)的字符,而不是在另一个字符串中搜索一个显式的字符列表。这样做的一个原因是,您可以利用其他标准库函数: 您可以传递 ctype.h 的‘ isunct’,而不是提供一个充满标点符号的显式字符串,等等。如果‘ isunct’只是作为一个宏来实现的,那么它就不会工作。
There are lots of other examples. For example, if your comparison is accomplished by macro rather than function, you can't pass it to stdlib.h's 'qsort'.