我不知道如何表达我的问题。代码如下,请告诉我为什么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
自身的有效(尽管有些非正统)分配。