为什么宏和函数对 c 中的相同代码的工作方式不同

Why macros and functions work differently about same code in c

我是编程新手,我发现了一个有趣但很难找到原因的问题,所以我写这个post。

我正在尝试编写交换函数:

当我用传统方式写swap函数时,

void swap(int *x,int *y){int t=*x;*x=*y;*y=t;}

此功能有效,当然,

void swap(int x,int y){int t=x;x=y;x=t;}

不起作用。但是当我把交换写成宏时,

#define swap(x,y){int t=x;x=y;y=t;} 作品...

为什么宏不用指针也可以交换值?

why the macro can swap value though they don't use pointer?

因为宏和函数的工作方式不同。 C 中的函数使用“按值调用”语义:当您将变量作为参数传递给函数时,只有该变量的值被发送到函数——函数不能更改变量本身。我们通过将指针传递给要更改的变量而不是变量本身来模拟“按引用调用”语义。它仍然是按值调用,因为函数仍然不能改变传入的东西,即地址,但它可以改变存储在该地址的值,这是我们想要什么。

另一方面,宏只是一个简单的文本替换;根本没有函数调用。当您使用 swap(x,y) 宏时,预处理器会将宏的定义插入该位置。这就好像你写了 {int t=x;x=y;y=t;} 而不是 swap(x,y)。当该代码运行时,它可以更改变量的值。

正如您已经猜到的那样,第一个有效但第二个无效,因为在第一个中,您将指针传递给要交换的变量,然后使用您想要交换的指针已经传递进来交换它们,有效地改变了存储在指针指向的位置的值。但是在第二个中,您只是传递变量的副本,因为 C 中的所有内容都是按值传递的。

然而,第三个有效,是因为宏 是简单的文本替换 通过预处理器标记替换工作(感谢 Eric Postpischil 指出宏不仅仅是简单的文本替换)。 所以考虑这段代码:

#define swap(x,y){int t=x;x=y;y=t;}
int main(void){
    int a=10;
    int b=20;
    swap(a,b);
}

这相当于:

int main(void){
 int a=10;
 int b=20;
 {int t=a;a=b;b=t;};
}

所以这里没有通过swap(a,b) 简单地替换为 {int t=a;a=b;b=t;}。您可以通过调用 cpp <file-name>.

来验证它