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

有人能给我举个例子解释一下宏与函数相比的缺点吗?

推荐答案

宏容易出错,因为它们依赖于文本替换,并且不执行类型判断.例如,此宏:

#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 碰巧包含一个名称相同但语义不同的字段,那么同一个宏可能对这两个 struct 都起作用,结果很奇怪:

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++具有许多特征,如模板,可以帮助在不使用宏的情况下以类型化的方式创建复杂的多态 struct ;详情请参见Stroustrup's The C++ Programming Language.

C++相关问答推荐

函数指针始终为零,但在解除引用和调用时有效

CC crate 示例不会与C函数链接

Apple Libm的罪恶功能

C/C++中的状态库

C中出现分段错误后关闭文件

如果包含路径不存在,我的编译器可以被配置为出错吗?(GCC、MSVC)

为什么GCC C23中的关键字FALSE不是整数常量表达式?

双指针指向常量双指针的指针类型赋值不兼容

为什么我会收到释放后堆使用错误?

pthread_create的用法

用C++高效解析HTTP请求的方法

隐藏测试用例无法在c程序中计算位数.

生成的头文件不包括用户定义的文件

当读取可能会阻塞管道中的父进程时,为什么要等待子进程?

C语言中的指针和多维数组

C 程序不显示任何输出,但它接受 CS50 Lab1 的输入问题

既然我们在 if 中将 int 的值更改为 10,为什么在第二个 fork 后,子进程及其创建的子进程都会打印 33 ?

一元运算符

如何修复数组数据与列标题未对齐的问题?

C11 嵌套泛型