Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用指针的变量的地址_C_Pointers - Fatal编程技术网

C 使用指针的变量的地址

C 使用指针的变量的地址,c,pointers,C,Pointers,考虑C语言中的以下代码 int x=100; int*addr=&x; 我知道addr将存储x的地址。我脑海中不断闪现的一个问题是addr指针将有自己的地址,可以使用符号和运算符再次访问,并且也将存储在某个地方,因此我们在这里对地址进行无限递归,那么这将结束于何处?如果存储地址,自然,您需要一些地方来存储它(即另一个地址),因此您可以继续此操作,只要您愿意。这正好在您希望它结束时结束 int a = 1; int *pa = &a; int

考虑C语言中的以下代码

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