C 使用指针的变量的地址
考虑C语言中的以下代码C 使用指针的变量的地址,c,pointers,C,Pointers,考虑C语言中的以下代码 int x=100; int*addr=&x; 我知道addr将存储x的地址。我脑海中不断闪现的一个问题是addr指针将有自己的地址,可以使用符号和运算符再次访问,并且也将存储在某个地方,因此我们在这里对地址进行无限递归,那么这将结束于何处?如果存储地址,自然,您需要一些地方来存储它(即另一个地址),因此您可以继续此操作,只要您愿意。这正好在您希望它结束时结束 int a = 1; int *pa = &a; int
int x=100;
int*addr=&x;
我知道addr将存储x的地址。我脑海中不断闪现的一个问题是addr指针将有自己的地址,可以使用符号和运算符再次访问,并且也将存储在某个地方,因此我们在这里对地址进行无限递归,那么这将结束于何处?如果存储地址,自然,您需要一些地方来存储它(即另一个地址),因此您可以继续此操作,只要您愿意。这正好在您希望它结束时结束
int a = 1;
int *pa = &a;
int **ppa = &pa;
int ***pppa = &ppa;
int ****ppppa = &pppa;
...
这里有一个简单的类比:假设你有一个带有页码和行号的笔记本。假设您在第3页第8行做了一个注释,然后您想从其他地方引用该注释。也许你可以在第7页第20行写一个参考“见第3页第8行的注释”。现在参考文献有了自己的“地址”——即第7页第20行。你也可以参考它——在第8页第1行,你可以写“见第7页第20行的注释”。您可以继续此引用链,只要您愿意。您没有无限递归。每个变量都有它的地址,就是它。现在,如果定义一个与另一个变量的地址相等的变量,那么地址变量本身将存储在某个地方,并具有一个地址。地址本身没有存储它的变量的地址 addr的地址不是显式地“存储”在任何地方,而是存储在任何地方。如果要声明第二个变量并使用它存储该地址,请确保它占用空间:
int **addr2 = &addr;
你可以把记忆想象成一系列的盒子。假设4字节int
和指针以及小尾端字节顺序,您的场景可能如下所示:
+----------+--+--+--+--+
| Address |Data bytes |
+----------+--+--+--+--+
|0x00000000|64|00|00|00|
+----------+--+--+--+--+
|0x00000004|00|00|00|00|
+----------+--+--+--+--+
地址显示在左侧,包含在该位置的字节显示在右侧。您可以看到存储在前四个字节中的值100
(100位十进制是十六进制中的0x64)。第二个4字节位置保存值0x00000000,这是x
的地址。地址0x00000004未存储在任何位置
现在,如果我们添加第二个指针,我们将使用更多内存:
+----------+--+--+--+--+
|0x00000008|04|00|00|00|
+----------+--+--+--+--+
这将是用于表示addr2
指针的内存,您可以看到它包含addr
的地址,即0x00000004
用表达式*addr2
取消引用addr2
将产生地址0x00000004处的值,即类型为int*
的0x00000000。再次取消引用将在该地址处生成int
,即0x00000064
由于此内存布局是由编译器选择的,因此它“知道”所涉及的地址,并且可以进行替换,以便当代码引用addr2
时,它生成操作地址0x00000008的指令,依此类推。在实际代码中,这可能都发生在堆栈上,但原理是一样的
最后一句话:听从老师的建议;上述内容简化并具体化了许多原本有点抽象的东西。这就是它在当今许多体系结构上的实际工作方式,但是所提到的许多东西并不是由C保证的,所以您不能真正依靠它们来始终保持正确。我的意思是,上面的说明(希望)能让这些概念变得不那么模糊。当然,地址指针会有自己的地址,但除非您特别访问它所持有的地址,否则它不会被使用,因此从概念上讲,它没有递归…,存储地址时,仅为指针分配存储空间: 1) 在您的情况下:
int*addr=&x代码>,addr
将占用sizeof(int*)
字节的内存。(但编译器保留不将指针存储在内存中的权利:它可能将指针保存在CPU寄存器中)
2) &x
不显式分配任何存储
3) &&x
,&&x
等在语法上无效,因此您无需担心此处可能出现的递归
&&
曾经是非法语法的事实允许C++11将其用于r值引用 让我们这样看。我们的内存有限。如果使用整个内存,则会为编译器分配有限的内存来存储变量。你可以根据自己的意愿声明任意多的变量,但总有一天你将无法生成更多的变量,因为分配的内存将耗尽空间。那么,对于你的问题,答案是否
。由于分配给存储变量的空间有限,因此没有无限递归。指针就像一座房子,它的地址在一个地方。房子是真实的,它的地址是找到房子的方法。假设有两栋房子,X和ptr,我需要存储一栋房子的地址(可能写在纸上),比如说另一栋房子的X,比如说ptr。
有了这个安排,如果我需要知道X的地址,我可以在ptr中查找,但X中有什么,我需要亲自访问房子。但目前我根本不想知道ptr的地址
更进一步
ptr and X are two houses.
//lets say &X is a sheet of paper containing the address of house X. I am going to keep this address in the house ptr. So the address of X is stored in ptr.
ptr = &X;
//Now what about ptr. Only if I need to know the address, I need to write the address in some paper and store it again in some other house. Else I am happy to know the house exits.
这取决于
这取决于编译器和优化级别。编译器可能决定不将指针“addr”存储在主内存中,而只是将其值保存在寄存器中,使用它在主内存中定位x。C实现了所谓的冯·诺依曼机器。你可以在其他类型的计算机上编译C,如果你能让计算机像冯·诺依曼机器那样工作的话
那么,什么是冯·诺依曼机器向BBC致歉后,大多数人认为内存中的程序对代码和数据有着严格而不同的概念,但实际上——从统一的冯·诺依曼的角度来看——程序的内存空间更像是一个大球,它是一个结实的、摇摇晃晃的、数量众多的wumbery。。。东西。您可以像访问数据一样访问甚至更改它,也可以像运行代码一样运行它。但是
int x = 100;
int*addr = &x;
/*
* show that a variable allocated on the heap sticks around, while a
* variable allocated on the stack vanishes after its enclosing
* function returns. Holding a pointer to the latter can lead to
* unexpected results.
*/
#include <stdio.h>
int heapvar = 20;
int *get_heapvar_ptr() {
return &heapvar;
}
int *get_stackvar_ptr() {
int stackvar = 30;
return &stackvar;
}
int main() {
int *heap_ptr = get_heapvar_ptr();
int *stack_ptr = get_stackvar_ptr();
/* should print value = 20 */
printf("heapvar address = %#x, heapvar value = %d\n", heap_ptr, *heap_ptr);
/* you might expect this to print value = 30, but it (probably) doesn't */
printf("stackvar address = %#x, stackvar value = %d\n", stack_ptr, *stack_ptr);
}
heapvar address = 0x22a8018, heapvar value = 20
stackvar address = 0x5d957fac, stackvar value = 0