如何理解" C ++允许sizeof(char *)!= sizeof(int *)"?

时间:2015-12-31 02:40:51

标签: c++ pointers language-lawyer

我正在阅读与charbyte相关的post,并且会出现以下字样:

  

int*仍然可以作为单个硬件指针实现,因为C ++允许sizeof(char*) != sizeof(int*)

如何理解' C ++允许sizeof(char*) != sizeof(int*)'?

5 个答案:

答案 0 :(得分:3)

有(或曾经)的机器只能处理整个“单词”,其中一个单词足够大以容纳多个字符。例如,PDP-6/10的字长为36位。在这样的机器上,您可以实现9位字节并将字节指针表示为字中的字指针和位索引的组合。对于这样的指针,一个天真的实现需要两个单词,即使整数指针只是一个单词指针,占用一个单词。

(真正的PDP-6/10允许更小的字符大小 - 6位和7位编码是常见的,取决于用例 - 并且由于指针不能占据整个字,因此可以制作包含位偏移和字地址的字符指针适合单个单词。但是现在类似的架构不会对地址空间有严格的限制,因此不再适用。)

答案 1 :(得分:2)

简而言之,标准并不保证,结果是实现定义的。

来自sizeof的标准($ 5.3.3 / 1 Sizeof [expr.sizeof])

  

sizeof运算符产生对象中的字节数   表示其操作数。

和指针是复合类型($ 3.9.2 / 1.3复合类型[basic.compound])

  

指向void或对象或函数的指针(包括静态成员)   给定类型的类,8.3.1;

和($ 3.9.2 / 3化合物类型[basic.compound])

  

指针类型的值表示为实现定义

即使($ 3.9.2 / 3复合类型[basic.compound])

  

布局兼容类型的指针应具有相同的值   表示和对齐要求(3.11)。

charint不需要具有相同的值表示。标准只说($ 3.9.1 / 2基本类型[basic.fundamental])

  

有五种标准的有符号整数类型:“signed char”,“short”   int“,”int“,”long int“和”long long int“。在此列表中,每种类型   提供至少与列表中前面的存储一样多的存储空间。

和($ 3.9.1 / 3基本类型[basic.fundamental])等。

  

每个有符号整数类型具有与其相同的对象表示   相应的无符号整数类型。

答案 2 :(得分:2)

itsnotmyrealname rici 触及硬件驱动程序,但我认为这可能有助于完成导致不同指针大小的最简单方案... < / p>

想象一下,CPU可以处理32位字的内存,而C ++ int类型也是32位宽。

这个假设的CPU使用编号对特定字进行寻址:第一个字为0(字节0-3),第二个为1(字节4-7),依此类推。因此,int*{0}是你记忆中的第一个词(假设没有奇怪的nullptr恶作剧要求),int*{1}第二个等等。

编译器应该怎样做才能支持8位char类型?它可能必须使用char*来实现int*支持以识别内存中的字,但仍需要额外的两位来存储0,1,2或3来说明该字中的哪个字节被指出。它实际上需要像C ++程序一样生成机器代码,如果使用...

struct __char_ptr
{
    unsigned* p_;
    unsigned byte_ : 2;
    char get() const { return (*p_ & (0xFF << (8*byte_)) >> 8*byte_; }
    void set(char c) { *p_ &= ~(0xFF << (8*byte_)); *p |= c << 8*byte_; }
};

在这样的系统上 - sizeof(__char_ptr) > sizeof(int*)。 C ++标准的灵活性允许具有此类或类似问题的奇怪系统的兼容C ++实现(以及代码可移植性)。

答案 3 :(得分:2)

这也是为什么we can not forward declare enums without providing the underlying size在我的回答中我提供了几个参考资料来解释为什么会这样的原因。

在此comp.lang.c++ discussion: GCC and forward declaration of enum中:

  

[...]虽然在大多数架构上,但在一些架构上可能不是问题   架构指针将具有不同的大小,以防它是一个   char指针。 [...]

我们可以从这个C-Faq条目Seriously, have any actual machines really used nonzero null pointers, or different representations for pointers to different types? 中找到它:

  

较旧的,字寻址的Prime机器也因为需要比字指针(int *)更大的字节指针(char *)而臭名昭着。 [...]某些64位Cray机器在一个字的低48位中表示int *; char *另外使用高16位中的一些来指示字内的字节地址。 [...]

此外:

  

[...] Data General的Eclipse MV系列有三种架构支持的指针格式(字,字节和位指针),其中两个由C编译器使用:字符指针用于char *和void *,以及其他一切的词指针。由于历史原因在从16位Nova线演变32位MV线期间,字指针和字节指针在字中的不同位置具有偏移,间接和环保护位。将不匹配的指针格式传递给函数会导致保护错误。最终,MV C编译器添加了许多兼容性选项,以尝试处理具有指针类型不匹配错误的代码。 [...]旧的HP 3000系列使用不同的字节地址寻址方案而不是字地址;就像它上面的几台机器一样,它使用char *和void *指针的不同表示而不是其他指针。 [...]

答案 4 :(得分:1)

标准说:

  

5.3.3尺寸
  sizeof(char),sizeof(signed char)和sizeof(unsigned char)是1。   sizeof应用于任何其他基本类型的结果(   3.9.1)是实现定义的。

由于指针是“复合类型”,并且标准没有提到指针之间的字节大小一致性,编译器编写者可以随心所欲地做。