我经常看到使用宏比使用函数更好的实例。
有人可以举例说明宏与函数相比的缺点吗?
最佳答案
宏很容易出错,因为它们依赖于文本替换并且不执行类型检查。例如,这个宏:
#define square(a) a * a
与整数一起使用时工作正常:
square(5) --> 5 * 5 --> 25
但是当与表达式一起使用时会做一些非常奇怪的事情:
square(1 + 2) --> 1 + 2 * 1 + 2 --> 1 + 2 + 2 --> 5
square(x++) --> x++ * x++ --> increments x twice
在参数两边加上括号会有所帮助,但并不能完全消除这些问题。
当宏包含多个语句时,您可能会遇到控制流构造的麻烦:
#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)”循环中。
如果您有两个结构恰好包含一个名称相同但语义不同的字段,则同一个宏可能对两者都起作用,但会产生奇怪的结果:
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),因为调试器无法单步调试宏,如本例所示:
#define print(x, y) printf(x y) /* accidentally forgot comma */
print("foo %s", "bar") /* prints "foo %sbar" */
内联函数和常量有助于避免许多此类宏问题,但并不总是适用。在故意使用宏来指定多态行为的地方,可能难以避免无意的多态性。 C++ 有许多功能,例如模板,可以帮助以类型安全的方式创建复杂的多态结构,而无需使用宏;有关详细信息,请参阅 Stroustrup 的 The C++ Programming Language。
关于c - C 中的宏与函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9104568/