C 中的宏与函数 [英] Macro vs Function in C

查看:17
本文介绍了C 中的宏与函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常看到使用宏比使用函数更好的例子.

I often see instances in which using a macro is better than using a function.

谁能用一个例子向我解释宏与函数相比的缺点?

Could someone explain me with an example the disadvantage of a macro compared to a function?

推荐答案

宏很容易出错,因为它们依赖于文本替换并且不执行类型检查.例如,这个宏:

Macros are error-prone because they rely on textual substitution and do not perform type-checking. For example, this macro:

#define square(a) a * a

与整数一起使用时效果很好:

works fine when used with an integer:

square(5) --> 5 * 5 --> 25

但是当与表达式一起使用时会做出非常奇怪的事情:

but does very strange things when used with expressions:

square(1 + 2) --> 1 + 2 * 1 + 2 --> 1 + 2 + 2 --> 5
square(x++) --> x++ * x++ --> increments x twice

在参数周围加上括号有帮助,但并不能完全消除这些问题.

Putting parentheses around arguments helps but doesn't completely eliminate these problems.

当宏包含多个语句时,您可能会遇到控制流结构的问题:

When macros contain multiple statements, you can get in trouble with control-flow constructs:

#define swap(x, y) t = x; x = y; y = t;

if (x < y) swap(x, y); -->
if (x < y) t = x; x = y; y = t; --> if (x < y) { t = x; } x = y; y = t;

解决此问题的常用策略是将语句放入do { ... } while (0)"循环中.

The usual strategy for fixing this is to put the statements inside a "do { ... } while (0)" loop.

如果有两个结构碰巧包含同名但语义不同的字段,则同一个宏可能对两者都起作用,结果很奇怪:

If you have two structures that happen to contain a field with the same name but different semantics, the same macro might work on both, with strange results:

struct shirt 
{
    int numButtons;
};

struct webpage 
{
    int numButtons;
};

#define num_button_holes(shirt)  ((shirt).numButtons * 4)

struct webpage page;
page.numButtons = 2;
num_button_holes(page) -> 8

最后,宏可能难以调试,产生奇怪的语法错误或运行时错误,您必须扩展才能理解(例如使用 gcc -E),因为调试器无法单步执行宏,如下例所示:

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:

#define print(x, y)  printf(x y)  /* accidentally forgot comma */
print("foo %s", "bar") /* prints "foo %sbar" */

内联函数和常量有助于避免宏的许多此类问题,但并不总是适用.在故意使用宏来指定多态行为的情况下,可能难以避免无意的多态性.C++ 有许多特性,例如模板,可以帮助以类型安全的方式创建复杂的多态结构,而无需使用宏;有关详细信息,请参阅 Stroustrup 的C++ 编程语言.

Inline functions and constants help to avoid many of these problems with macros, but aren't always applicable. Where macros are deliberately used to specify polymorphic behavior, unintentional polymorphism may be difficult to avoid. C++ has a number of features such as templates to help create complex polymorphic constructs in a typesafe way without the use of macros; see Stroustrup's The C++ Programming Language for details.

这篇关于C 中的宏与函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆