在关于C的一个有信誉的来源中,在讨论&操作符后给出了以下信息:
... 有点不幸的是,术语[地址的]仍然存在,因为它混淆了那些不知道地址是关于什么的人,并误导了那些知道地址的人:将指针视为地址通常会导致悲伤……
我读过的其他材料(来自同样有名望的来源,我想说)总是毫不掩饰地将指针和&操作符作为内存地址。我很愿意继续寻找事情的真相,但当有信誉的消息来源不同意时,这有点困难。
现在我有点困惑了——如果指针不是内存地址,那么它到底是什么?
P.S.
作者后来说:……不过,我将继续使用“地址”这个术语,因为发明一个不同的(术语)会更糟糕。
很难确切地说出这些书的作者到底是什么意思。指针是否包含地址取决于如何定义地址和如何定义指针。
从所有的回答来看,有些人认为(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)方面的+/-差异)。
A pointer value is an address. A pointer variable is an object that can store an address. This is true because that's what the standard defines a pointer to be. It's important to tell it to C novices because C novices are often unclear on the difference between a pointer and the thing it points to (that is to say, they don't know the difference between an envelope and a building). The notion of an address (every object has an address and that's what a pointer stores) is important because it sorts that out.
然而,标准在特定的抽象层次上进行讨论。作者所说的那些“知道地址是关于什么的”,但对C不熟悉的人,必须在不同的抽象级别上学习地址——也许是通过编写汇编语言。不能保证C实现使用与cpu操作码相同的地址表示(在本文中称为“存储地址”),这些人已经知道。
He goes on to talk about "perfectly reasonable address manipulation". As far as the C standard is concerned there's basically no such thing as "perfectly reasonable address manipulation". Addition is defined on pointers and that is basically it. Sure, you can convert a pointer to integer, do some bitwise or arithmetic ops, and then convert it back. This is not guaranteed to work by the standard, so before writing that code you'd better know how your particular C implementation represents pointers and performs that conversion. It probably uses the address representation you expect, but it it doesn't that's your fault because you didn't read the manual. That's not confusion, it's incorrect programming procedure ;-)
简而言之,C使用了比作者更抽象的地址概念。
The author's concept of an address of course is also not the lowest-level word on the matter. What with virtual memory maps and physical RAM addressing across multiple chips, the number that you tell the CPU is "the store address" you want to access has basically nothing to do with where the data you want is actually located in hardware. It's all layers of indirection and representation, but the author has chosen one to privilege. If you're going to do that when talking about C, choose the C level to privilege!
Personally I don't think the author's remarks are all that helpful, except in the context of introducing C to assembly programmers. It's certainly not helpful to those coming from higher level languages to say that pointer values aren't addresses. It would be far better to acknowledge the complexity than it is to say that the CPU has the monopoly on saying what an address is and thus that C pointer values "are not" addresses. They are addresses, but they may be written in a different language from the addresses he means. Distinguishing the two things in the context of C as "address" and "store address" would be adequate, I think.
指针是表示内存位置的抽象。请注意,这句话并没有说把指针当作内存地址是错误的,它只是说它“通常会导致悲伤”。换句话说,它会让你产生错误的期望。
The most likely source of grief is certainly pointer arithmetic, which is actually one of C's strengths. If a pointer was an address, you'd expect pointer arithmetic to be address arithmetic; but it's not. For example, adding 10 to an address should give you an address that is larger by 10 addressing units; but adding 10 to a pointer increments it by 10 times the size of the kind of object it points to (and not even the actual size, but rounded up to an alignment boundary). With an int * on an ordinary architecture with 32-bit integers, adding 10 to it would increment it by 40 addressing units (bytes). Experienced C programmers are aware of this and put it to all kinds of good uses, but your author is evidently no fan of sloppy metaphors.
There's the additional question of how the contents of the pointer represent the memory location: As many of the answers have explained, an address is not always an int (or long). In some architectures an address is a "segment" plus an offset. A pointer might even contain just the offset into the current segment ("near" pointer), which by itself is not a unique memory address. And the pointer contents might have only an indirect relationship to a memory address as the hardware understands it. But the author of the quote cited doesn't even mention representation, so I think it was conceptual equivalence, rather than representation, that they had in mind.