繁体   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