在关于C的一个有信誉的来源中,在讨论&操作符后给出了以下信息:
... 有点不幸的是,术语[地址的]仍然存在,因为它混淆了那些不知道地址是关于什么的人,并误导了那些知道地址的人:将指针视为地址通常会导致悲伤……
我读过的其他材料(来自同样有名望的来源,我想说)总是毫不掩饰地将指针和&操作符作为内存地址。我很愿意继续寻找事情的真相,但当有信誉的消息来源不同意时,这有点困难。
现在我有点困惑了——如果指针不是内存地址,那么它到底是什么?
P.S.
作者后来说:……不过,我将继续使用“地址”这个术语,因为发明一个不同的(术语)会更糟糕。
马克·贝西(Mark Bessey)已经说过了,但这一点需要再次强调,直到人们理解为止。
指针与变量的关系比与文字3的关系更大。
指针是一个值(地址)和类型(带有其他属性,如只读)的元组。类型(以及附加参数(如果有的话)可以进一步定义或限制上下文;如。__far ptr, __near ptr:地址的上下文是什么:堆栈,堆,线性地址,某处的偏移量,物理内存或其他。
正是type的属性使得指针算术与整数算术略有不同。
指针不是变量的反例太多了,不容忽视
fopen返回FILE指针。(变量在哪里)
堆栈指针或帧指针通常是不可寻址的寄存器
*(int *)0x1231330 = 13;——将任意整数值转换为pointer_of_integer类型,并在不引入变量的情况下写入/读取整数值
在c程序的生命周期中,会有许多其他没有地址的临时指针实例——因此它们不是变量,而是带有编译时相关类型的表达式/值。
C或c++指针与简单内存地址的另一个不同之处是,我在其他答案中没有看到不同的指针类型(尽管考虑到它们的总大小,我可能忽略了它)。但它可能是最重要的一个,因为即使是经验丰富的C/ c++程序员也会被它绊倒:
编译器可能会假设不兼容类型的指针不指向相同的地址,即使它们很明显指向相同的地址,这可能会导致简单的pointer==address模型不可能出现的行为。考虑以下代码(假设sizeof(int) = 2*sizeof(short)):
unsigned int i = 0;
unsigned short* p = (unsigned short*)&i;
p[0]=p[1]=1;
if (i == 2 + (unsigned short)(-1))
{
// you'd expect this to execute, but it need not
}
if (i == 0)
{
// you'd expect this not to execute, but it actually may do so
}
注意,char*有一个例外,所以使用char*操作值是可能的(尽管不是很可移植)。
以下是我过去是如何向一些困惑的人解释的:
指针有两个影响其行为的属性。它有一个值(在典型环境中)是一个内存地址,还有一个类型(告诉您它所指向的对象的类型和大小)。
例如,给定:
union {
int i;
char c;
} u;
你可以有三个不同的指针都指向同一个对象:
void *v = &u;
int *i = &u.i;
char *c = &u.c;
如果你比较这些指针的值,它们都是相等的:
v==i && i==c
但是,如果对每个指针加1,就会发现它们所指向的类型变得相关了。
i++;
c++;
// You can't perform arithmetic on a void pointer, so no v++
i != c
此时,变量i和c将具有不同的值,因为i++使i包含下一个可访问的整数的地址,而c++使c指向下一个可寻址的字符。通常,整数比字符占用更多的内存,所以在它们都加一之后,i的值将比c的值更大。