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

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

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

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

P.S.

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


当前回答

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

其他回答

它说“因为它让那些不知道地址是什么的人感到困惑”——而且,这是真的:如果你知道地址是什么,你就不会困惑了。从理论上讲,指针是一个指向另一个变量的变量,实际上保存着一个地址,即它所指向的变量的地址。我不知道为什么要隐瞒这个事实,这又不是什么高深的科学。如果你理解了指针,你就离理解计算机的工作原理更近了一步。去吧!

指针只是另一个变量,用来保存内存位置的地址(通常是另一个变量的内存地址)。

你是对的,是理智的。通常,指针只是一个地址,因此您可以将其强制转换为整数并进行任何算术运算。

但有时指针只是地址的一部分。在一些体系结构上,指针被转换为一个增加了基数的地址或使用另一个CPU寄存器。

但是现在,在PC和ARM架构上,使用平面内存模型和原生编译的C语言,可以认为指针是指向一维可寻址RAM中某个位置的整数地址。

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

从所有的回答来看,有些人认为(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指针是相对丰富的类型。如果在一个结构数组中增加一个指针,它会很好地从一个结构跳到另一个结构。

指针服从转换规则,并提供编译时类型检查。

有一个特殊的“空指针”值,它在源代码级别是可移植的,但其表示可能不同。如果将值为0的整型常量赋给指针,则该指针的值为空指针。同样,如果你用这种方式初始化一个指针。

指针可以用作布尔变量:如果指针不是null,则为true;如果指针为null,则为false。

在机器语言中,如果空指针是一个有趣的地址,如0xFFFFFFFF,那么您可能必须对该值进行显式测试。C把它藏起来了。即使空指针是0xFFFFFFFF,你也可以使用if (ptr != 0) {/* not null!* /}。

Uses of pointers which subvert the type system lead to undefined behavior, whereas similar code in machine language might be well defined. Assemblers will assemble the instructions you have written, but C compilers will optimize based on the assumption that you haven't done anything wrong. If a float *p pointer points to a long n variable, and *p = 0.0 is executed, the compiler is not required to handle this. A subsequent use of n will not necessary read the bit pattern of the float value, but perhaps, it will be an optimized access which is based on the "strict aliasing" assumption that n has not been touched! That is, the assumption that the program is well-behaved, and so p should not be pointing at n.

在C语言中,指向代码的指针和指向数据的指针是不同的,但在许多体系结构中,它们的地址是相同的。可以开发具有“胖”指针的C编译器,即使目标体系结构没有。胖指针意味着指针不仅仅是机器地址,还包含其他信息,例如用于边界检查的被指向对象的大小信息。可移植编写的程序将很容易移植到这样的编译器。

所以你可以看到,在机器地址和C指针之间有很多语义上的区别。