ISO/IEC 9899:1990 编程语言 C 关于 short int、int、long 的定义
Posted
技术标签:
【中文标题】ISO/IEC 9899:1990 编程语言 C 关于 short int、int、long 的定义【英文标题】:ISO/IEC 9899:1990 programming Language C definition about short int, int, long 【发布时间】:2020-10-20 07:03:49 【问题描述】:Blockquote “ISO/IEC 9899:1990, Programming Languages - C (ISO C) 故意模糊了 short int、int、long int 和指针的定义,以避免人为地限制可能受益的硬件架构定义这些数据类型彼此独立。唯一的限制是 ints 必须不小于 shorts,longs 必须不小于 ints,并且 size_t 必须表示实现支持的最大无符号类型。例如,这是可能的,定义一个short为16位,一个int为32位,一个long为64位,指针为128位。基本数据类型之间的关系可以表示为: sizeof(char) http://www.unix.org/whitepapers/64bit.html
为什么我们需要将这些数据类型定义得如此模糊
是不是因为我们有不同的计算机架构,所以我们无法将 int 设置为 32 位的固定大小?
long 和 int64 有什么区别? 是不是long的大小由系统决定,int64保证64位?
感谢您的帮助
【问题讨论】:
"size_t 必须代表实现支持的最大无符号类型" --> 确定吗? 你在引用什么?请注明取自其他来源的文字。 这些类型的大小随时间而变化。 未来打样。当我们进行 1024 位计算时,编码大小的语言会做什么?überlong
? holy<expletive deleted>itsbig
?
int64_t
直到 99 才出现。C 中没有定义 int64
。
【参考方案1】:
首先,必须指出的是,C 是在非常早期的计算机时代发明的,基于 1960 年代的 B 和 BCPL 语言。当时存在许多不同的实验性计算机 - 没有人知道哪些会幸存下来或成为行业标准。
正因为如此,C 语言甚至支持三种不同形式的有符号数格式:1 的补码、2 的补码和有符号的量值。其中 1 的补码和有符号幅度允许带有特殊行为,例如陷阱表示或填充位。但是,所有现代现实世界的计算机中约有 99.999% 使用 2 的补码,因此所有这些都非常无益。
为什么我们需要将这些数据类型定义得如此模糊
我们没有。不给整数类型一个固定的大小和符号可以说是一个幼稚的设计错误。过去的基本原理是允许 C 在尽可能多的不同计算机上运行。事实证明,这与在不同计算机之间移植 C 代码完全不同。
懒惰的程序员可能会发现在不考虑整数限制的情况下到处乱发垃圾邮件int
很方便,然后得到一个“合适的、足够大的本地符号整数”。但是,例如,当我们需要使用 16 位 2 的补码时,这一点帮助都没有。或者当我们需要优化尺寸时。或者当我们使用 8 位 CPU 并希望尽可能避免任何大于 8 位的东西时。
所以int
和朋友们不太便携:大小和签名格式是未知的并且跨平台不一致,使得这些所谓的“原始数据类型”具有潜在的危险和/或低效。
更糟糕的是,int
的不可预测行为与其他语言缺陷相冲突,例如隐式 int 类型提升(请参阅 Implicit type promotion rules),或者像 1
这样的整数常量始终为 int
的事实。这些规则旨在将每个表达式转换为int
,以防止不称职的程序员在进行算术运算时对小的有符号整数类型进行溢出。
例如int8_t i8=0; ... i8 = i8 + 256;
在 C 中实际上不会导致有符号溢出,因为该操作是在类型 int
上执行的,然后将其转换回小整数类型 int8_t
(尽管在实现定义的方式)。
然而,隐含的提升规则总是弊大于利。当从 16 位系统移植到 32 位系统时,您的 unsigned short
可能会突然无声地变成 signed int
。这反过来又会产生各种微妙的错误,尤其是在使用按位运算符/编写与硬件相关的代码时。这些规则在小整数类型和大整数类型在表达式中的工作方式之间造成了不一致。
为了解决其中一些问题,stdint.h
早在 1999 年就在该语言中引入。它包含像 uint8_t
这样的类型,无论系统如何,都保证具有固定大小。并且它们保证是 2 的补码。此外,我们可以使用像uint_fast8_t
这样的类型来让编译器为给定的系统选择最适合的类型,可移植。现在大多数专业的 C 软件——尤其是嵌入式系统——只使用 stdint.h
类型,从不使用本机类型。
stdint.h
使移植代码更容易,但并不能真正解决隐式提升问题。为了解决这些问题,必须用更强大的类型系统重写该语言,并强制所有整数转换都必须使用强制类型转换显式。由于没有希望 C 得到修复,因此开发了该语言的安全子集,例如 MISRA-C 和 CERT-C。这些文档中有很大一部分致力于解决隐式转换错误。
关于size_t
的注释,特别是保证它是无符号的并且“足够大”,但仅此而已。他们并没有真正考虑到定义它应该代表什么。物体的最大尺寸?数组?还是只是sizeof
返回的类型?它与 ptrdiff_t
之间存在意外的依赖关系 - 另一个语言缺陷 - 请参阅 this exotic problem 我在使用 size_t
表示数组的最大允许大小时遇到。
【讨论】:
感谢您的友好回复。很有帮助!【参考方案2】:为什么我们需要将这些数据类型定义得如此模糊
根据你的摘录,原因是
避免人为地限制硬件架构,这可能 受益于独立于其他数据类型定义这些数据类型
不过,我觉得这个措辞有点尴尬。基本思想是,该标准允许针对不同硬件架构的 C 实现为自然适合硬件的各种类型选择大小。这不仅仅是关于 32 位 vs。顺便说一句,64位。我个人使用过 8 位、16 位、32 位和 64 位计算机,并且我曾开发过最初为具有 36 位和其他原生字长的计算机编写的软件。这就是我可以声称与任何类型的个人联系的原因。计算硬件的过去、现在和可能的未来的多样性比我怀疑你所理解的要大得多,但是 C 可以在非常广泛的种类上有效地实现。
long 和 int64 有什么区别?是不是long的大小由系统决定,int64保证64位?
C 语言没有定义任何名为int64
的类型。尤其是您摘录中引用的版本C90,没有提供。最新版本的 C 定义了一个类型 int64_t
,实现不需要提供。在可用的情况下,它是一个整数类型,只有一个符号位、63 个值位,并且没有填充位,以二进制补码形式表示。在某些系统上,long
和 int64_t
是同一类型,而在其他系统上,它们是不同的类型。还有一些,没有int64_t
。例如,在 Microsoft 的 C 实现中,long
即使在 64 位硬件上也是 32 位类型。
【讨论】:
感谢您的回复。欣赏。以上是关于ISO/IEC 9899:1990 编程语言 C 关于 short int、int、long 的定义的主要内容,如果未能解决你的问题,请参考以下文章
C++20标准 (ISO/IEC 14882:2020) 正式发布