簡體   English   中英

如何理解“C ++允許sizeof(char *)!= sizeof(int *)”?

[英]How to understand “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位編碼很常見,具體取決於用例 - 並且因為指針不能占用整個單詞,所以可以制作一個字符指針包括位偏移和字地址適合單個單詞。但現在類似的架構不會對地址空間有嚴格的限制,因此不再適用。)

簡而言之,標准並不能保證,結果是實現定義的。

從關於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])等

每個有符號整數類型具有與其對應的無符號整數類型相同的對象表示。

itsnotmyrealnamerici觸及硬件驅動程序,但我認為這可能有助於完成導致不同指針大小的最簡單的可能情況......

想象一下,CPU可以處理32位字的內存,而C ++ int類型也是32位寬。

該假設的CPU使用編號對特定字進行尋址:第一個字為0(字節0-3),第二個為1(字節4-7),依此類推。 int*{0}因此是你內存中的第一個單詞(假設沒有奇怪的nullptr shenanigans否則), int*{1}第二個等等。

編譯器應該怎么做才能支持8位char類型? 它可能必須使用int*來實現char*支持以識別內存中的字,但仍需要額外的兩位來存儲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 ++實現(以及代碼可移植性)。

這也是為什么我們不能沒有提供我的答案中的基礎大小的情況下轉發聲明枚舉的原因我提供了幾個參考,涵蓋了為什么會這樣。

在這個comp.lang.c ++討論中:GCC和枚舉的前向聲明

[...]雖然在大多數體系結構上它可能不是問題,但在某些體系結構上,指針將具有不同的大小,以防它是char指針。 [...]

我們可以從這個C-Faq條目中找到真的,有任何實際的機器真的使用非零空指針,或指向不同類型的指針的不同表示? 它說:

較舊的,字尋址的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 *指針的不同表示而不是其他指針。 [...]

標准說:

5.3.3尺寸
sizeof(char),sizeof(signed char)和sizeof(unsigned char)是1。 sizeof應用於任何其他基本類型(3.9.1)的結果是實現定義的。

由於指針是“復合類型”,並且標准沒有提到指針之間的字節大小一致性,因此編譯器編寫者可以隨心所欲地執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM