"指针指向另一个内存位置 "是什么意思?

问题描述 投票:0回答:1

我知道指针变量存储的是另一个变量的内存地址。但它的意思是 "指针指向另一个内存位置"? 这句话是什么意思?"指针指向..."?

c pointers memory-address
1个回答
0
投票

从根本上来说,一个 可变的 是一个名称和内存中的一个位置之间的关联。在其他语言中,它可能比这更复杂,其他信息通常与变量相关联(例如类型),但这与这里无关。

指针变量是一个变量(一个引用内存中某个区域的名称),但这个内存区域里有什么?是什么呢?指针 本身?嗯,它是一个内存地址,是引用另一个内存位置的方式。而不是说 "指针 有价值 这个其他的内存位置",我们说指针 参考文献指向 这另一个内存位置。

我们可以给这另一个内存位置起个名字。这将使它成为一个变量。因此,我们也可以说指针是 参考文献指向 这个其他变量。

在下面的代码中,我们有一个指针--------。p 归属 i:

int i = 1000;
int *p = &i;

我们可能有这个记忆。

p at addr 0x1122       |      ⋮       |
i at addr 0x3344       +--------------+
                       |       0x3344 | 0x1122
                       +--------------+
                       |      ⋮       |
                       +--------------+
                       |         1000 | 0x3344
                       +--------------+
                       |      ⋮       |

那么下面两个语句有什么区别呢?

int *q = p;
int j = *p;

在第一个语句中,我们复制的是指针本身,即内存地址。

在第二条语句中,我们是间接地访问 i. 我们告诉C 提述 指针,也就是访问指针所指向的东西。这就是 i.

我们可能有这个记忆。

p at addr 0x1122       |      ⋮       |
i at addr 0x3344       +--------------+
q at addr 0x5566       |       0x3344 | 0x1122
j at addr 0x7788       +--------------+
                       |      ⋮       |
                       +--------------+
                       |         1000 | 0x3344
                       +--------------+
                       |      ⋮       |
                       +--------------+
                       |       0x3344 | 0x5566
                       +--------------+
                       |      ⋮       |
                       +--------------+
                       |         1000 | 0x7788
                       +--------------+
                       |      ⋮       |

如果你改变了其中一个人,其他人会怎么样?*p, *q, ij? 我让你假设和实验:)


0
投票

它指向另一个内存位置,就像你最近收到的明信片上的邮政地址指向你的家一样。一个指针包含了一个内存位置的地址。邮政地址包含了一个物理位置的地址--无论是一栋楼,一间公寓,一个邮政信箱......。因此,"指向 "的意思是 "指的是一个位置的"。指向和邮政地址都是如此。

并不是说指针一定要指向以下地点 另一个 内存位置。的确,在现实世界的软件中,绝大多数使用的指针确实指向其他地方。那就是 99.9...% 世界上任何时候存在的指针的数量,小数点后还有15个九。最起码是这样的。

但指针也肯定可以指向自己。有时候,如果你只想把指针插在某个地方,并了解这个 "地方 "在哪里,那就很方便了。例如,在大多数C和C++的实现中,下面的短程序将打印出指针变量在运行时驻留的堆栈地址(是的,实现中不必将该变量存储在堆栈上,但在大多数实际情况下,它确实会是一个堆栈地址)。

#include <stdio.h>

int main() {
  void *pointer = &pointer;
  printf("The variable \"%s\" is stored on stack at address %p\n", "pointer", &pointer);
}

例如,我得到了以下输出。

The variable "pointer" is stored on stack at address 0x7fff2350e9f8

一个指针也可能指向 没有 内存位置。空指针就是一个例子。

// Conformant C and C++
int *nullPointer1 = NULL; // Idiomatic C
int *nullPointer2 = 0;
// Conformant C++
int *nullPointer3 = nullptr; // Idiomatic C++
int *nullPointer4 = {}; // Idiomatic C++
std::unique_ptr<int> nullPointer5; // This is really C++ - raw pointers should be used only when truly needed, in library code etc.

这样的指针是可以的,但唯一有效的用途是检查它们是否真的是空的。它们不能被取消引用--我的意思是,是的,你可以取消引用它们,但这是未定义的行为,而现代编译器将你代码中未定义的行为视为删除此类代码的许可。也就是说,如果你取消引用一个空指针,而编译器可以证明它总是如此,那么做这种取消引用的代码可能会被删除。例子(gcc 10.1 x64, -O3):

int main() {
  int *pointer = 0;
  int b = *pointer;
}

// produces same assembly output as
int main() { return 0; }

它变得更好。这段代码。

int main() {
   int *pointer = 0;
   *pointer = 5;
}

编译时,第二行的修改就像你写了 *pointer = 0,紧接着任务之后是 ub2 "指令",触发未定义指令异常。换句话说:如果你在一个映射了第0-3个内存页的进程中运行这条指令,它就会失败,即使加载了 5 在地址 0 会是一个有效的操作!相反,它会加载 0 在地址 0,然后以异常方式失败。

© www.soinside.com 2019 - 2024. All rights reserved.