蛊毒传说
宏容易出错,因为宏依赖于文本替换并且不执行类型检查。例如,此宏:#define square(a) a * a与整数一起使用时可以正常工作:square(5) --> 5 * 5 --> 25但是当与表达式一起使用时,会做非常奇怪的事情:square(1 + 2) --> 1 + 2 * 1 + 2 --> 1 + 2 + 2 --> 5square(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的C ++编程语言。