我不知道如何表达我的问题。代码如下,请告诉我为什么a改变了值?在我看来,GET macro只是返回的值a,而不是a...的地址
#include <stdio.h>
#define GET(addr) (*(int *)(&addr))
int main()
{
int a = 10;
GET(a) = 20;
printf("%d\n", a);
}
我不知道如何表达我的问题。代码如下,请告诉我为什么a改变了值?在我看来,GET macro只是返回的值a,而不是a...的地址
#include <stdio.h>
#define GET(addr) (*(int *)(&addr))
int main()
{
int a = 10;
GET(a) = 20;
printf("%d\n", a);
}
当你扩展你的宏时,你会得到:
(*(int *)(&a)) = 20
忘记(int *)你就会得到
(*(&a)) = 20
这等于:
a = 20;
因此,您正在改变a!
该GET(a) = 20行扩展为:
(*(int *)(&a)) = 20;
让我们去掉多余的演员表和外括号:
*(&a) = 20;
这显然是一个任务,a因为它相当于:
a = 20;
如果您的目标是防止意外使用GET()左值,您可以像这样更改它:
#define GET(addr) ((int)addr)
有了这个,尝试编译你的代码失败了
test.c:8:12: error: lvalue required as left operand of assignment
假设你有:
int *b = ...;
*b = 10;
上面所做的是将 10 分配给指向的整数b。
你的宏做几乎相同的事情,b替换为&a(和无操作演员)。
取消引用指针的结果是L-value,因为它有一个地址;它当然可以分配。
考虑一个更简单的例子:如果p是一个数组或一个指针,你当然可以分配给p[0],如
p[0] = 20;
现在回想一下,p[0]这与*p. 现在扩展你的宏:
*((int*)&a) = 20;
这相当于
(&a)[0] = 20;
这当然是对a自身的有效(尽管有些非正统)分配。