概要
(我还将放在顶部):
(0)将指针视为地址通常是一种很好的学习工具,并且通常是指向普通数据类型的指针的实际实现。
(1)但是,在许多(也许是大多数)编译器中,指向函数的指针不是地址,而是大于地址(通常为2x,有时更大),或者实际上是指向内存中结构的指针,而不是包含函数和诸如此类的东西的地址一个恒定的池。
(2)指向数据成员的指针和指向方法的指针通常甚至更陌生。
(3)具有FAR和NEAR指针问题的旧版x86代码
(4)带有安全“胖指针”的几个示例,最著名的是IBM AS / 400。
我相信您可以找到更多。
详情:
嗯!!!!!! 到目前为止,许多答案都是相当典型的“程序员中间人”答案,但不是编译器中间人或硬件中间人。由于我假装自己是一个硬件weenie,并且经常与编译器weenies一起工作,所以让我投入两分钱:
在许多(可能是大多数)C编译器上,指向类型数据的指针T
实际上是的地址T
。
精细。
但是,即使在许多这样的编译器上,某些指针也不是地址。您可以通过查看来告诉我们sizeof(ThePointer)
。
例如,指向函数的指针有时比普通地址大很多。或者,它们可能涉及间接级别。 本文提供了一个涉及Intel Itanium处理器的描述,但我看到了其他描述。通常,要调用函数,您不仅必须知道函数代码的地址,而且还必须知道函数的常量池的地址-内存区域,使用单个加载指令从中加载常量,而不是编译器必须生成几个立即加载,移位和或指令中的64位常量。因此,您需要2个64位地址,而不是单个64位地址。一些ABI(应用程序二进制接口)以128位为单位进行移动,而另一些ABI使用间接级别,函数指针实际上是包含刚刚提到的2个实际地址的函数描述符的地址。哪个更好?取决于您的观点:性能,代码大小,以及一些兼容性问题-通常代码会假定指针可以强制转换为long或long long,但也可能会假设long long恰好是64位。这样的代码可能不符合标准,但是客户可能希望它可以工作。
我们中的许多人对NEAR POINTER和FAR POINTERS都怀念旧的Intel x86分段架构。幸运的是,现在这些几乎已经绝迹了,因此仅作一个简短的总结:在16位实模式下,实际的线性地址为
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
而在保护模式下,可能是
LinearAddress = SegmentRegister[SegNum].base + offset
根据段中设置的限制检查结果地址。有些程序使用的并不是真正的标准C / C ++ FAR和NEAR指针声明,但是许多程序只是说*T
---但是有编译器和链接器开关,因此,例如,代码指针可能位于指针附近,仅比指针中的32位偏移。 CS(代码段)寄存器,而数据指针可能是FAR指针,同时为16位段号和32位偏移量指定48位值。现在,这两个数量肯定与地址有关,但是由于它们的大小不同,因此哪个是地址?此外,除了与实际地址有关的内容外,这些网段还具有权限-只读,读写,可执行。
一个更有趣的例子,恕我直言,是(或者也许是)IBM AS / 400系列。这台计算机是最早用C ++实现操作系统的计算机之一。这个指针上的指针通常是实际地址大小的2倍-例如,此演示文稿例如128位指针,但实际地址为48-64位,此外,还提供了一些额外的信息,即所谓的功能,该功能提供了诸如读取,写入之类的权限以及防止缓冲区溢出的限制。是的:您可以与C / C ++兼容地执行此操作-并且如果这无所不在,那么中国的PLA和斯拉夫黑手党就不会侵入如此众多的西方计算机系统。但是历史上大多数C / C ++编程都忽略了性能的安全性。最有趣的是,AS400系列允许操作系统创建安全的指针,该指针可以提供给未特权的代码,但未特权的代码无法伪造或篡改。同样,安全性虽然符合标准,但草率的非符合标准的C / C ++代码在这样的安全系统中将无法工作。同样,有官方标准,
现在,我将离开安全性提示框,并提到通常不能真正解决(各种类型的)指针的其他一些方式:指向数据成员的指针,成员函数方法的指针以及它们的静态版本大于普通地址。正如这篇文章 所说:
解决这个问题的方法有很多种[与单人或多人继承和虚拟继承有关的问题]。这是Visual Studio编译器决定处理它的方式:指向多重继承类的成员函数的指针实际上是一个结构。”然后他们继续说:“投射函数指针可以改变其大小!”。
从对安全性的高度评价中可以猜到,我参与了C / C ++硬件/软件项目,在该项目中,指针被视为功能而非原始地址。
我可以继续,但希望您能明白。
概要
(我还将放在顶部):
(0)将指针视为地址通常是一种很好的学习工具,并且通常是指向普通数据类型的指针的实际实现。
(1)但是,在许多(也许是大多数)编译器中,指向函数的指针不是地址,而是大于地址(通常为2X,有时更大),或者实际上是指向内存中的结构的指针,而不包含函数和诸如此类的东西一个恒定的池。
(2)指向数据成员的指针和指向方法的指针通常甚至更陌生。
(3)具有FAR和NEAR指针问题的旧版x86代码
(4)带有安全“胖指针”的几个示例,最著名的是IBM AS / 400。
我相信您可以找到更多。