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

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

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

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

P.S.

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


当前回答

简单地说,指针实际上是分割机制的偏移部分,分割后转换为线性地址,分页后转换为物理地址。物理地址实际上是从ram中寻址的。

       Selector  +--------------+         +-----------+
      ---------->|              |         |           |
                 | Segmentation | ------->|  Paging   |
        Offset   |  Mechanism   |         | Mechanism |
      ---------->|              |         |           |
                 +--------------+         +-----------+
        Virtual                   Linear                Physical

其他回答

我不确定你的来源,但你描述的语言类型来自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,但在另一个系统上使用相同的代码/值可能会使程序崩溃)。

结果比我想象的要长……

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

例如:

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;
}

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

A pointer, like any other variable in C, is fundamentally a collection of bits which may be represented by one or more concatenated unsigned char values (as with any other type of cariable, sizeof(some_variable) will indicate the number of unsigned char values). What makes a pointer different from other variables is that a C compiler will interpret the bits in a pointer as identifying, somehow, a place where a variable may be stored. In C, unlike some other languages, it is possible to request space for multiple variables, and then convert a pointer to any value in that set into a pointer to any other variable within that set.

Many compilers implement pointers by using their bits store actual machine addresses, but that is not the only possible implementation. An implementation could keep one array--not accessible to user code--listing the hardware address and allocated size of all of the memory objects (sets of variables) which a program was using, and have each pointer contain an index into an array along with an offset from that index. Such a design would allow a system to not only restrict code to only operating upon memory that it owned, but also ensure that a pointer to one memory item could not be accidentally converted into a pointer to another memory item (in a system that uses hardware addresses, if foo and bar are arrays of 10 items that are stored consecutively in memory, a pointer to the "eleventh" item of foo might instead point to the first item of bar, but in a system where each "pointer" is an object ID and an offset, the system could trap if code tried to index a pointer to foo beyond its allocated range). It would also be possible for such a system to eliminate memory-fragmentation problems, since the physical addresses associated with any pointers could be moved around.

Note that while pointers are somewhat abstract, they're not quite abstract enough to allow a fully-standards-compliant C compiler to implement a garbage collector. The C compiler specifies that every variable, including pointers, is represented as a sequence of unsigned char values. Given any variable, one can decompose it into a sequence of numbers and later convert that sequence of numbers back into a variable of the original type. Consequently, it would be possible for a program to calloc some storage (receiving a pointer to it), store something there, decompose the pointer into a series of bytes, display those on the screen, and then erase all reference to them. If the program then accepted some numbers from the keyboard, reconstituted those to a pointer, and then tried to read data from that pointer, and if user entered the same numbers that the program had earlier displayed, the program would be required to output the data that had been stored in the calloc'ed memory. Since there is no conceivable way the computer could know whether the user had made a copy of the numbers that were displayed, there would be no conceivable may the computer could know whether the aforementioned memory might ever be accessed in future.

简单地说,指针实际上是分割机制的偏移部分,分割后转换为线性地址,分页后转换为物理地址。物理地址实际上是从ram中寻址的。

       Selector  +--------------+         +-----------+
      ---------->|              |         |           |
                 | Segmentation | ------->|  Paging   |
        Offset   |  Mechanism   |         | Mechanism |
      ---------->|              |         |           |
                 +--------------+         +-----------+
        Virtual                   Linear                Physical