c ++编译器如何理解指针类型?我知道指针的大小等于OS的WORD(32或64)。那么它是否存储了关于类型的32(或64)位的一些信息?只是因为你不能在一个类型上有一个指针并为该指针分配另一个具有不同类型的指针。
答案 0 :(得分:10)
编译器知道指针的类型,因为源代码指出指针的类型:
int* ip; // ip is a pointer to an int
float* fp; // fp is a pointer to a float
void* vp; // vp is a pointer to some unknown type; need to cast it to a pointer
// to an actual type in order to access the pointed-at object
答案 1 :(得分:4)
指针通常只是基于x86架构的内存地址(我不了解其他架构)。编译器在编译时使用不同的指针强制执行类型安全 - 例如,将指针指向char指定为指向int的指针是没有意义的,特别是因为指向的对象是不同的大小(所以你要如果你访问它们就抓住随机内存)。您可以显式覆盖此指针,并将任何指针指向任何其他指针reinterpret_cast<T>
,或指定其他类型的指针,如static_cast<T>
和dynamic_cast<T>
(后两者通常建议由于'更安全'但每个都有它们的用途。)
因此,在机器级别,内存地址只是一个内存地址,CPU将尽职尽责地执行任何访问或调用。然而它很危险,因为你可以把类型混淆起来并且可能不知道它。编译时检查有助于避免这种情况,但通常没有任何关于运行时指针本身内存储的实际类型的信息。
使用迭代器(STL提供的指针包装器)的一个优点是许多实现都有许多额外的检查,可以在运行时启用:比如检查你是否正在使用正确的容器,当你比较它们时,它们是相同类型的迭代器,依此类推。这是使用迭代器而不是指针的一个主要原因 - 但标准并不要求它,因此请检查您的实现。
答案 2 :(得分:4)
正如James所说,编译器“知道”指针的类型,因为你告诉它。
然而,不那么轻浮,在封面下发生的事情(在一个非常简单的解释中)是解析器在读取代码时,用它需要检查的信息和执行规则来注释它的每个重要部分。它所识别的语言。所以给出了这个示例代码:int* ip;
// do some stuff
double* dp = ip;
编译器将在幕后执行类似的操作(再次以粗略简化的形式):
嗯......这个叫做“ip”的东西。我最好记下它是一个整数指针。好的,这就是所谓的“dp”。我最好记下它是一个双指针。好的,现在,他想将ip分配给dp。但是......坚持下去! ip是一个整数,dp是double。我做不到!...编译器在屏幕上呕吐......
现实同时也比上面简单得多(因为计算机根本没有想到任何东西 - 它都是非常机械的)而且更加复杂(因为我在那个机械上掩盖了大约十亿个细节)处理)。
答案 3 :(得分:1)
这是将源代码转换为机器代码的语法分析的一部分。在最简单的示例中,您可以将其视为检查赋值两侧的类型:
dest = source
// make sure that type of source == type of dest
答案 4 :(得分:1)
指针只保存一个内存地址,仅此而已。
意识到在汇编级别(所有C / C ++代码都被转换为),实际上并没有任何类型的概念,就像高级语言一样。 ASM指令都对二进制值(字节,字,双字等)进行操作,而不过多关注程序是否认为给定的一组位是int,char或其他东西。
(当然,除了我们对整数值与浮点值进行操作有不同的指令这一事实,但这不是本讨论的重点。)
简而言之,该类型完全是一个编译时构造,存储在编译器程序本身的symbol table内,将标识符映射到类型。在正在编译的程序中,类型不存在。
答案 5 :(得分:0)
大小等于操作系统的WORD
CPU word
你想说什么?最重要的是不要使用word
来描述类型,因为术语严重超载,并且根据读者的背景可能很容易被误解。
仅仅是因为你不能在一个类型上有一个指针并为该指针分配另一个具有不同类型的指针。
取决于。请继续阅读:Von Neumann architecture
答案 6 :(得分:0)
在现代体系结构中,没有关于内存字是命令,数字,字符串的一部分还是指针的运行时信息。编译完成后,所有这些信息都会丢失(尽管它可能仍在调试符号中可用)。如果一个单词被编译代码用作指针,那么它必须是一个指针 - CPU不会检查你。
用于在运行时维护此信息的较旧,更具异国情调的架构。看看这里:http://wapedia.mobi/en/Burroughs_large_systems?p=2