针对:
int *a;
a
是一个整数可以被存储的地址。
&a
是存储a的地址。
那么,&a
存储在哪里?
&(&a)
存储在哪里?
&(&(&a))
存储在哪里?
这种地址的存储会一直持续下去吗?
针对:
int *a;
a
是一个整数可以被存储的地址。
&a
是存储a的地址。
那么,&a
存储在哪里?
&(&a)
存储在哪里?
&(&(&a))
存储在哪里?
这种地址的存储会一直持续下去吗?
如果你没有明确写出 &a
,它将不会被存储在任何地方。如果你写了,那么地址将被计算并存储在一个未命名的变量(临时变量)或者一个你写的命名变量中。
例如:
functionCall( &a ); // address will be in a temporary variable used for passing the parameter
int** b = &a; // address will be stored in variable b
otherFunctionCall( &&a ); // illegal, since &a is an expression operator & can't be applied to it
a
存储在堆栈中,就像任何其他局部变量一样。当你写 &a
时,程序计算出存储 a
的堆栈中的地址(它已经知道了堆栈指针,因为它是一个寄存器,并且它知道堆栈帧中的偏移量,因为它被编译为常量),并对其进行操作,如 sharptooth 所解释的那样。 - rmeadora
不是“存储整数的地址”。a
是一个足够大的变量,可以容纳一个整数的地址。你唯一可以直接存储在a
中的“整数”是整数的地址,将其视为整数本身:
int *a;
int b;
a = &b;
printf("a is now %x\n", (unsigned int) a);
确实,a
本身有一个地址,即&a
,但该地址在运行时没有被明确存储在某个地方。
如果勉强说的话,您可能能够存储类似于整数0的内容:
a = 0;
但这只是“空指针”的简写语法,即保证不是任何实际对象地址的指针值。
&a
is a constant.
&(&a)
is illegal.
&a是a的地址。它是运算符&应用于a的结果值,并且不被“存储”,没有地址,因此&(&a)是无效的。这就像2+3。
int *a
"是一个指针变量的大小,就像"int b
"是一个自动整数变量一样。b = &a; //the address in the executable's .DATA or on the stack (if `a` auto)
c = &b; //the address of `b` on the stack, independent of `a` or `&a`
d = &c; //the address of `c` on the stack, independent of `a` or `&a`
z = &(&a); //error: invalid lvalue in unary '&'
&
要求操作数必须是左值
,也就是可赋值的东西——像上面的b
和c
。而(&a)
是一个没有存储在任何地方的表达式的结果,因此不是左值
。int value = 742;
int *a = &value;
void *b = &a;
void *c = &b;
void *d = &c;
如果不将其分配给任何变量,您不会将其放在单行上-在这种情况下,它将无效。
你可以有一个指向指针的指针。
例如:
void foo(int **blah)
{
int *a = *blah;
...
}
&a是一个rvalue的数字:如果您想要在已声明或分配的int*类型变量中存储它,则可以将其存储在某个地方。
也就是说:
int a = 42;
&a; /* this does not store the address of a because you've not assigned the value to a variable */
int **aptr = &a; /* aptr is on the stack */
int **aptr2 = (int*)malloc(sizeof(int*));
aptr2 = &a; /* aptr2 is in the heap */
&(&a) 不是合法的语法。 如果你想要一个指向指针的 int:
int b = 39;
int *bptr = &b;
int **ptr2bptr = &bptr;
你必须建立起间接级别。
有了上述内容,如果你想的话,可以这样做:
printf("%d\n", *aptr);
printf("%d\n", *aptr2);
printf("%d\n", *bptr);
printf("%d\n", **ptr_to_bptr);
42
42
39
39