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



我正在阅读这篇与charbyte有关的文章,并遇到了以下单词:

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

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

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

(真正的PDP-6/10允许更小的字符大小——根据使用情况,6位和7位编码很常见——而且由于指针不能占据整个单词,因此可以将包括位偏移量和单词地址的字符指针放在一个单词中。但如今类似的架构不会对地址空间有严格的限制,所以这无论如何都不起作用。)ore。)

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

来自关于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)。

但CCD_ 7和CCD_。标准只说(3.9.1/2美元基本型〔basic.basic〕)

有五种标准的有符号整数类型:"signed char"、"shortint"、"int"、"long int"one_answers"long long int"。在此列表中,每种类型提供的存储空间至少与列表中位于其前面的存储空间一样多。

和(3.9.1/3美元基本型〔basic.basic〕)等

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

itsnotmyrealnamerici触及了这方面的硬件驱动程序,但我认为通过最简单的可能导致不同指针大小的场景可能会有所帮助。。。

想象一下,一个CPU可以寻址32位的内存字,并且C++int类型也是32位宽。

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

编译器应该做些什么来支持8位char类型?它可能必须使用int*来实现对char*的支持,以识别内存中的字,但仍然需要额外的两位来存储0、1、2或3,以说明该字中的哪个字节被指向。如果使用。。。

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++实现,用于存在此问题或类似问题的奇怪系统(以及代码的可移植性)。

这也是为什么我们不能在不提供基本大小的情况下转发声明枚举的原因。在我的回答中,我提供了一些参考,涵盖了为什么会这样。

在这个comp.lang.c++讨论中:GCC和枚举的前向声明:

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

我们可以从这个C-Faq条目中发现。说真的,有没有真正的机器使用非零零指针,或者不同类型指针的不同表示?上面写着:

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

此外:

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

标准规定:

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

由于指针是"复合类型",并且标准没有提及指针之间的字节大小一致性,因此编译器编写器可以随心所欲。

最新更新