在关于C的一个有信誉的来源中,在讨论&操作符后给出了以下信息:

... 有点不幸的是,术语[地址的]仍然存在,因为它混淆了那些不知道地址是关于什么的人,并误导了那些知道地址的人:将指针视为地址通常会导致悲伤……

我读过的其他材料(来自同样有名望的来源,我想说)总是毫不掩饰地将指针和&操作符作为内存地址。我很愿意继续寻找事情的真相,但当有信誉的消息来源不同意时,这有点困难。

现在我有点困惑了——如果指针不是内存地址,那么它到底是什么?

P.S.

作者后来说:……不过,我将继续使用“地址”这个术语,因为发明一个不同的(术语)会更糟糕。


当前回答

指针是一个保存内存地址的变量,而不是地址本身。但是,您可以解除对指针的引用-并访问内存位置。

例如:

int q = 10; /*say q is at address 0x10203040*/
int *p = &q; /*means let p contain the address of q, which is 0x10203040*/
*p = 20; /*set whatever is at the address pointed by "p" as 20*/

就是这样。就是这么简单。

一个演示我所说内容的程序,其输出如下:

http://ideone.com/rcSUsb

程序:

#include <stdio.h>

int main(int argc, char *argv[])
{
  /* POINTER AS AN ADDRESS */
  int q = 10;
  int *p = &q;

  printf("address of q is %p\n", (void *)&q);
  printf("p contains %p\n", (void *)p);

  p = NULL;
  printf("NULL p now contains %p\n", (void *)p);
  return 0;
}

其他回答

很难确切地说出这些书的作者到底是什么意思。指针是否包含地址取决于如何定义地址和如何定义指针。

从所有的回答来看,有些人认为(1)地址必须是整数,(2)指针不需要是虚的,因为规范中没有这么说。根据这些假设,显然指针不一定包含地址。

然而,我们看到,虽然(2)可能是真的,(1)可能不一定是真的。根据@ corn秸秆的答案,&被称为操作符的地址,这是怎么回事?这是否意味着规范的作者希望指针包含地址?

我们可以说,指针包含一个地址,但地址不一定是整数?也许吧。

我认为所有这些都是废话连篇的迂腐语义学。实际上,这是毫无价值的。你能想到一个编译器以这样的方式生成代码,指针的值不是一个地址吗?如果有,是什么?我也是这么想的……

我认为这本书的作者(第一个摘录声称指针不一定只是地址)可能指的是指针自带固有类型信息这一事实。

例如,

 int x;
 int* y = &x;
 char* z = &x;

y和z都是指针,但y+1和z+1是不同的。如果它们是内存地址,难道这些表达式不会给你相同的值吗?

在这里,把指针当作地址的想法通常会导致悲伤。之所以会出现bug,是因为人们将指针视为地址,而这通常会导致不幸。

55555可能不是指针,尽管它可能是一个地址,但(int*)55555是一个指针。55555+1 = 55556,但是(int*)55555+1是55559(在sizeof(int)方面的+/-差异)。

指针只是另一个变量,它通常包含另一个变量的内存地址。指针是一个变量,它也有一个内存地址。

C标准没有在内部定义指针是什么以及它在内部是如何工作的。这样做的目的是为了不限制平台的数量,在这些平台上,C可以作为编译或解释语言实现。

指针值可以是某种ID或句柄,也可以是几个ID的组合(对x86段和偏移量说你好),不一定是真正的内存地址。这个ID可以是任何东西,甚至是固定大小的文本字符串。非地址表示可能对C解释器特别有用。

在这幅图中,

Pointer_p是一个位于0x12345的指针,它指向0x34567的变量variable_v。

我不确定你的来源,但你描述的语言类型来自C标准:

6.5.3.2地址和间接操作符 […] 3.一元&操作符产生其操作数的地址。[…]

所以…是的,指针指向内存地址。至少这是C标准所暗示的意思。

更清楚地说,指针是保存某个地址值的变量。对象的地址(可以存储在指针中)使用一元&操作符返回。

我可以将地址“42 Wallaby Way, Sydney”存储在一个变量中(该变量将是某种“指针”,但由于这不是一个内存地址,所以我们不能正确地称之为“指针”)。您的计算机有内存桶的地址。指针存储地址的值(例如,指针存储值“42 Wallaby Way, Sydney”,这是一个地址)。

编辑:我想对Alexey Frunze的评论进行扩展。

指针到底是什么?让我们看看C标准:

6.2.5类型 […] 20.[…] 指针类型可以从函数类型或对象类型派生,称为引用类型。指针类型描述了一个对象,该对象的值提供了对所引用类型实体的引用。从引用类型T派生的指针类型有时称为“指向T的指针”。从引用类型构造指针类型称为“指针类型派生”。指针类型是一个完整的对象类型。

从本质上讲,指针存储一个值,该值提供对某些对象或函数的引用。种。指针用于存储提供对某些对象或函数引用的值,但情况并非总是如此:

6.3.2.3指针 […] 5. 整数可以转换为任何指针类型。除非像前面指定的那样,否则结果是由实现定义的,可能没有正确对齐,可能没有指向引用类型的实体,并且可能是陷阱表示。

The above quote says that we can turn an integer into a pointer. If we do that (that is, if we stuff an integer value into a pointer instead of a specific reference to an object or function), then the pointer "might not point to an entity of reference type" (i.e. it may not provide a reference to an object or function). It might provide us with something else. And this is one place where you might stick some kind of handle or ID in a pointer (i.e. the pointer isn't pointing to an object; it's storing a value that represents something, but that value may not be an address).

是的,正如Alexey Frunze所说,指针可能没有存储对象或函数的地址。有可能一个指针存储的是某种“句柄”或ID,你可以通过给指针赋某个任意整数值来做到这一点。这个句柄或ID表示什么取决于系统/环境/上下文。只要您的系统/实现能够理解这个值,您就处于良好的状态(但这取决于具体的值和具体的系统/实现)。

通常,指针存储对象或函数的地址。如果它没有存储实际的地址(到对象或函数),则结果是实现定义的(这意味着究竟发生了什么以及指针现在表示什么取决于您的系统和实现,因此它可能是特定系统上的句柄或ID,但在另一个系统上使用相同的代码/值可能会使程序崩溃)。

结果比我想象的要长……