簡體   English   中英

ISO/IEC 9899:1990 編程語言 C 關於short int, int, long 的定義

[英]ISO/IEC 9899:1990 programming Language C definition about short int, int, long

Blockquote “ISO/IEC 9899:1990,編程語言 - C (ISO C) 故意模糊了 short int、int、long int 和指針的定義,以避免人為地限制可能從定義這些數據中受益的硬件架構類型相互獨立。唯一的限制是 int 必須不小於 shorts,longs 必須不小於 ints,並且 size_t 必須表示實現支持的最大無符號類型。例如,可以定義short 為 16 位,int 為 32 位,long 為 64 位,指針為 128 位。基本數據類型之間的關系可以表示為:sizeof(char) <= sizeof(short) <= sizeof( int) <= sizeof(long) = sizeof(size_t)" http://www.unix.org/whitepapers/64bit.html

為什么我們需要將這些數據類型定義得如此模糊

那是因為我們有不同的計算機體系結構,所以我們不能將 int 設置為 32 位的固定大小嗎?

long 和 int64 有什么區別? long 的大小是否由系統決定,int64 保證為 64 位?

感謝幫助

為什么我們需要將這些數據類型定義得如此模糊

根據您的摘錄,原因是

避免人為地限制可能受益於獨立於其他數據類型定義這些數據類型的硬件架構

不過,我覺得這個措辭有點尷尬。 基本思想是,該標准允許針對不同硬件架構的 C 實現來選擇自然適合硬件的各種類型的大小。 這不僅僅是 32 位. 順便說一句,64位。 我個人使用過 8 位、16 位、32 位和 64 位計算機,並且我曾開發過最初為具有 36 位和其他原生字長的計算機編寫的軟件。 這就是我可以聲稱與之有任何個人聯系的原因。 計算硬件的過去、現在和可能的未來的多樣性比我懷疑你理解的要大得多,但是 C 可以在非常廣泛的種類上有效地實現。

long 和 int64 有什么區別? long 的大小是否由系統決定,int64 保證為 64 位?

C 語言沒有定義任何名為int64的類型。 尤其是您摘錄中引用的版本C90,沒有提供。 更新版本的 C 定義了一個類型int64_t ,實現不需要提供。 如果可用,它是一個 integer 類型,只有一個符號位、63 個值位和沒有填充位,以二進制補碼形式表示。 在某些系統上, longint64_t是相同的類型,而在其他系統上,它們是不同的類型。 還有一些,沒有int64_t 例如,在 Microsoft 的 C 實現中, long是 32 位類型,即使在 64 位硬件上也是如此。

首先,必須注意的是,C 是在非常早期的計算機時代發明的,基於 1960 年代的 B 和 BCPL 語言。 當時存在許多不同的實驗計算機——沒有人完全知道哪些計算機會幸存下來或成為行業標准。

正因為如此,C 語言甚至支持三種不同的 forms 有符號數格式:1 的補碼、2 的補碼和有符號的幅度。 其中 1 的補碼和有符號幅度允許帶有特殊行為,例如陷阱表示或填充位。 但是大約 99.999% 的現代現實世界計算機使用 2 的補碼,所以所有這些都非常無用。

為什么我們需要將這些數據類型定義得如此模糊

我們沒有。 沒有給 integer 類型提供固定大小和簽名可以說是一個幼稚的設計錯誤。 過去的基本原理是允許 C 在盡可能多的不同計算機上運行 事實證明,這與在不同計算機之間移植C 代碼完全不同。

懶惰的程序員可能會發現在不考慮int限制的情況下到處亂扔垃圾郵件很方便,然后得到一個“合適的、足夠大的 integer 的本地簽名”。 但是,例如,當我們需要使用 16 位 2 的補碼時,這一點幫助都沒有。 或者當我們需要優化尺寸時。 或者當我們使用 8 位 CPU 並希望盡可能避免任何大於 8 位的東西時。

所以int & friends 不太便攜:大小和簽名格式是未知的並且跨平台不一致,使得這些所謂的“原始數據類型”具有潛在的危險和/或效率低下。

更糟糕的是, int的不可預測行為與其他語言缺陷相沖突,例如隱式 int 類型提升(請參閱隱式類型提升規則),或者像1這樣的 integer 常量始終為int的事實。 這些規則旨在將每個表達式都轉換為int ,以使不稱職的程序員免於自己的麻煩,以防他們對小的簽名 integer 類型進行溢出運算。

例如int8_t i8=0; ... i8 = i8 + 256; int8_t i8=0; ... i8 = i8 + 256; 實際上不會導致 C 中的有符號溢出,因為該操作是在int類型上執行的,然后將其轉換回小的 integer 類型int8_t (盡管以實現定義的方式)。

然而,隱含的晉升規則總是弊大於利。 當從 16 位系統移植到 32 位系統時,您的unsigned short可能會突然無聲地變成有signed int 這反過來又會產生各種微妙的錯誤,尤其是在使用按位運算符/編寫與硬件相關的代碼時。 這些規則在小型 integer 類型和大型 integer 類型在表達式中的工作方式之間產生了不一致。

為了解決其中一些問題, stdint.h早在 1999 年就在該語言中引入。它包含像uint8_t這樣的類型,無論系統如何,都保證具有固定大小。 並且保證它們是 2 的補碼。 此外,我們可以使用像uint_fast8_t這樣的類型來讓編譯器為給定的系統選擇最適合的類型,可移植。 現在最專業的 C 軟件 - 特別是嵌入式系統 - 只使用stdint.h類型,從不使用本機類型。

stdint.h使移植代碼更容易,但它並不能真正解決隱式提升問題。 為了解決這些問題,必須使用更強大的類型系統重寫該語言,並強制所有 integer 轉換必須使用強制轉換顯式。 由於 C 沒有希望得到修復,因此開發了該語言的安全子集,例如 MISRA-C 和 CERT-C。 這些文檔中有很大一部分致力於解決隱式轉換錯誤。


特別是關於size_t的注釋,它保證是無符號的並且“足夠大”,但僅此而已。 他們並沒有真正考慮到定義它應該代表什么。 object 的最大尺寸? 數組? 或者只是sizeof返回的類型? 它和ptrdiff_t之間存在意外的依賴關系 - 另一個語言缺陷 - 請參閱我在使用size_t表示數組的最大允許大小時遇到的這個奇異問題

暫無
暫無

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

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