如果我有一个指向整数的指针,例如:
int num = 12;
int *p = #
然后打印地址
printf("%p\n", (void*)p);
上一个和这个有什么区别:
printf("%p\n", (void*)&p);
如果我有一个指向整数的指针,例如:
int num = 12;
int *p = #
然后打印地址
printf("%p\n", (void*)p);
上一个和这个有什么区别:
printf("%p\n", (void*)&p);
这里,p
包含 的地址num
,所以第一个printf
输出 的地址num
。
另一方面,&p
是 的地址p
,所以第二个printf
打印的是 的地址p
。
使用该"%p"
格式,仅使用 plainp
将打印变量的内容p
,即指针变量p
指向的地址。
当您使用时,&p
您将获得变量的地址p
,即指向p
(在您的类型的情况下int **
)的指针并打印该指针。
你可以这样看:
+----+ +---+ +-----+ | &p | -> | p | -> | 编号 | +----+ +---+ +-----+
换句话说,&p
指向p
哪个指向num
。
如果您继续并尝试使用*p
,那将无法按预期工作。它将取消引用指针p
,即它将导致该位置的值p
是指针(num
在这种特定情况下,变量及其值)。*p
是一个类型的值,int
并且试图使用格式"%p"
来打印它会导致未定义的行为,因为*p
它不是指针而是一个值,并且"%p"
格式需要一个指针。
很可能不会发生任何不好的事情,并且在指针大小与指针大小相同的系统上int
(这是大多数 32 位系统)然后声明
printf("%p", (void *) *p);
只会打印c
,这是十六进制值12
,即 的值num
。
但是,如果指针的大小与 a 的大小不同,就像在典型的 64 位系统上一样,那么输出将无法预测,并且看起来几乎完全随机。int
以你为例——
int num = 12;
int *p = # // store address of num in pointer p
printf("%p\n", (void*)p); // line 1
printf("%p\n", (void*)&p); // line 2
第 1 行- 在此它将打印num
存储在指针中的变量的地址p
。因此,存储在指针中的值p
是整数变量的地址num
。
第 2 行- 在这个指针p
本身的地址中将被打印出来。注意operator的地址的使用。它给出了指针的地址p
。
(void*)&p
表示 p 的地址。
(void*)p
表示 p 的内容(在这种情况下是 的地址)num
。
(void*)*p
表示变量指向的内容( ) (的值)。p
12
num
有关地址运算符的更多详细信息,请参见http://www.c4learn.com/c-programming/c-pointer-address-operator/。
前者打印 num 的地址。后者打印指针 p 的地址。因为,一切都需要在内存中的一个位置来存储。
如果你取一个整数,它有一个存储它的物理地址,并且数据(一个整数)存储在那个位置。
如果你拿一个指针,它也有一个物理地址,它存储在内存中,但这里的数据变成另一个地址,它是某个整数变量的地址。
& 称为运算符的地址。它返回存储特定变量的内存地址。按照同样的例子,
printf("%p\n", (void*)p);
打印指针 p 指向的数据。即num的地址。
可以使用类似的结果,
printf("%p\n", (void*)&num);
因此,两者都会产生相同的结果。
然而,
printf("%p\n", (void*)&p);
打印指针 p 的地址。
printf("%p\n", (void*)p);
打印p
包含的值,即 的地址num
。
printf("%p\n", (void*)&p);
打印指针p
本身的地址。
您可以在 ac/c++ 函数中传递两种类型的参数。
第一个是按值调用,它在程序中调用(void)p 之类的东西,它复制相同的值,并且该特定 void 函数中的值不会改变。
第二个是通过引用调用,它实际上进入内存并找出那个特定的位置/地址并在那里改变它的值。在你的情况下(无效)&p