c - C 中的宏与函数

标签 c function c-preprocessor

我经常看到使用宏比使用函数更好的实例。

有人可以举例说明宏与函数相比的缺点吗?

最佳答案

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

#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/

相关文章:

python - 尝试从 C 调用 Python

c - D-Bus 列表名称

Javascript循环创建函数并使用收到的基于PHP查询的id附加值

c - 在 C 中使用 define 在所有特定函数调用之后或之前添加语句

c++ - 有什么方法可以生成重复的 operator<< 定义?

c - void 究竟是什么意思?它如何以这种奇怪的方式使用?

混淆使用 fork() 和 wait(),这也是最有效的方法吗?

javascript - 如何从存储在数组中的对象返回键

javascript - 检查每个 div 是否有一个元素,里面有一个特定的类

c++ - 如何在一行中检查没有定义任何预处理器宏?