私は自分の問題を表現する方法がわかりません。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
したがって、 !の値を変更しています。
ポインターを逆参照した結果はL-valueです。これは、アドレスがあるためです。それは確かに割り当てることができます。
より簡単な例を考えてみましょう:が配列またはポインターの場合、次のように にp
確実に割り当てることができますp[0]
p[0] = 20;
p[0]
と同じであることを思い出して*p
ください。マクロを展開します。
*((int*)&a) = 20;
これは、
(&a)[0] = 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;
上記は、b
指し示す整数に 10 を割り当てます。
あなたのマクロは、 (およびノーオペレーションキャスト)にb
置き換えられて、ほとんど同じことを行います。&a