【问题标题】:What does it mean by a "pointer points to another memory location"?“指针指向另一个内存位置”是什么意思?
【发布时间】:2023-03-16 10:14:01
【问题描述】:

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

【问题讨论】:

  • t 表示指针指向“另一个变量的内存地址”,即指针变量的值是“另一个变量的内存地址”。
  • @Paul Ogilvie 谢谢!
  • “指针p指向变量x”只是“变量p的值是变量x的内存地址”的另一种说法。至少在最直接的实现中是这样。
  • @NSR 这是一个面试测试。一个候选人给出了一个错误的答案,指针指向左边,他被告知指针指向另一个内存位置:它指向右边。:)

标签: c pointers memory-address


【解决方案1】:

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

指针变量是一个变量(引用某个内存区域的名称),但该内存区域中有什么? pointer 本身是什么?嗯,它是一个内存地址,一种引用另一个内存位置的方式。与其说“指针具有值这个其他内存位置”,我们说指针references指向这个其他内存位置。

我们可能有另一个内存位置的名称。这将使它成为一个变量。因此,我们也说指针 references指向 这个其他变量。

在下面,我们有一个指针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。我们告诉 Cdereference 指针,这意味着访问指针指向的那个。这是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*qij 之一,其他人会怎样?我会让你假设和实验:)

【讨论】:

  • 我已添加到我的答案中。
【解决方案2】:

它指向另一个内存位置,就像您最近收到的明信片上的邮政地址指向您的家一样。指针包含内存位置的地址。邮政地址包含物理位置的地址 - 无论是建筑物、公寓还是邮局……“指向”因此意味着“指的是”的位置。指针和邮政地址都是如此。

指针必须指向另一个内存位置是不正确的。确实,现实世界软件中使用的绝大多数指针确实指向其他地方。那是99.9...% 在任何给定时间世界上存在的指针,小数点后还有 15 个 9。至少,最起码。

但是一个指针当然也可以指向它自己。有时,如果您只想在某处放置一个指针,并了解这个“某处”在哪里,这会很方便。例如,在大多数 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

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

// 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 个内存页的进程中运行它,它会失败,即使在地址 0 加载 5 将是一个有效的操作!相反,它会在地址0 处加载0,然后失败并出现异常。

【讨论】:

    猜你喜欢
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2021-01-04
    • 2011-01-27
    • 2012-11-02
    • 1970-01-01
    • 2014-06-25
    相关资源
    最近更新 更多