C程序中整数的历史typedef汤是什么?

Mic*_*eld 48 c

这是一个可能无聊的问题,我应该知道它的答案.

十五年前左右,我所看到的很多C代码在平台特定的#ifdefs 中有大量的整数typedef .似乎我看过的每个程序或库都有自己的,互不兼容的typedef汤.我当时并不知道很多关于编程的内容,只是为了告诉编译器你想要使用什么类型的整数,它似乎是一个奇怪的箍.

我已经在脑海中编写了一个故事来解释那些typedef是关于什么的,但我实际上并不知道它是否属实.我的猜测基本上是当C首次开发和标准化时,没有意识到能够平台独立地获得特定大小的整数类型是多么重要,因此所有原始C整数类型可能是不同的不同平台上的尺寸.因此,每个尝试编写可移植C代码的人都必须自己编写代码.

它是否正确?如果是这样,如何程序员预计将使用C整数类型?我的意思是,在一个低级别的语言中,有很多有点麻烦,能说"这是一个32位整数"并不重要吗?自从该语言在1989年被标准化以来,肯定有人认为人们会尝试编写可移植代码吗?

Joh*_*all 66

当C开始时,计算机的同质性较低,而且与现在的连接相比要少得多.对于可移植性来说,更重要的是int类型是计算机的自然大小.在36位系统上要求精确的32位整数类型可能会导致代码效率低下.

然后是普适的网络,您正在使用特定的线上大小字段.现在,互操作性看起来有很大不同.而'八位字节'成为事实上的数据类型量子.

现在你需要8位精确倍数的整数,所以现在你得到了typedef汤,然后最终标准赶上了,我们有标准的名字,并且汤不是必需的.

  • "在36位系统上要求一个准确的32位整数类型可能会导致代码效率低下."如果你只需要32位,你就无法解决这个问题.如果它必须至少为32位,则有int_fast32_t. (4认同)
  • 我同意,但我觉得今天的计算机不像20世纪90年代末那样异构(请记住Unix战争和工作站战争:Appollo,HP,IBM,Sun,......) (3认同)
  • 我显然是少数人的意见,即使在今天,如果你有充分的理由去写C,你通常不需要,也不应该想要一个_fixed_-width积分类型:而是选择你是否想要保证保持所需尺寸的最小或最快的类型.编译器总是有机会最好地了解它 - 告诉它你需要多少位,以及是否更喜欢运行时或运行空间效率,并让它从那里处理它. (3认同)
  • @mtraceur总的来说,我同意,但有时你需要一定大小的行为来实现互操作性或algorythymic正确性 - 校验和,序列号环绕等 - 其中具有确切的预期大小极大地简化和加速了事情. (3认同)
  • 现货,这个.坦率地说,可变宽度类型对于大多数目标而言是过时的(尽管在低功率世界中仍然有用).总的来说,除非你知道你因为它们而存在严重的瓶颈,否则固定宽度类型的规则是正常的.你知道它们是什么,你知道它们做了什么,你知道它们有多大......在网络或文件序列化层的任何一侧.现在您只需要谨慎对待字节序和对齐,然后就可以了. (2认同)

chu*_*ica 18

C的早期成功是由于它能够灵活地适应几乎所有现有的变体架构@John Hascall:
1)原生整数大小为8,16,18,24,32,36等位,
2)变量有符号整数模型: 2的补码,1的补码,有符号整数和
3)各种端序,大,小和其他.

随着编码的发展,数据的算法和交换推动了更大的一致性,因此需要跨平台满足1和2的类型.编码器就像typedef int int32在里面一样#if ....如OP所述,其中的许多变化产生了汤.


C99引入(u)int_leastN_t, (u)int_fastN_t, (u)intmax_t了便携式但有些最小位宽度类型.N = 8,16,32,64需要这些类型.

还介绍了半可选类型(见下面的**)(u)intN_t,它们具有附加属性,它们必须是2的补码且没有填充.正是这些流行的类型被广泛需要并用于稀释整数汤.


程序员如何期望使用C整数类型?

通过编写不强烈依赖于位宽的灵活代码.strtol()仅使用LONG_MIN, LONG_MAX不考虑位宽/字节/整数编码的代码是相当容易的.

然而,许多编码任务需要精确的宽度类型和2的补码,以便于高性能编码.在这种情况下,最好放弃36位机器的便携性和32位符号幅度的机器,并坚持2 N宽(带符号2的补码)整数.我想到了各种CRC和加密算法和文件格式.因此需要固定宽度类型和指定(C99)方式来做到这一点.


今天仍然存在仍需要管理的陷阱.示例:通常的促销int/unsigned会失去一些控制权,因为这些类型可能是16,32或64.


**

这些类型是可选的.但是,如果实现提供宽度为8,16,32或64位的整数类型,没有填充位,并且(对于带有二进制补码表示的有符号类型),它应定义相应的typedef名称.C11 7.20.1.1确切宽度整数类型3


Yim*_*ong 11

我记得那个时期,我也犯了同样的罪行!

一个问题是它的大小int,它可以是相同的short,long或者在它们之间.例如,如果您使用的是二进制文件格式,则必须保持一致.字节也可以订购复杂的东西.许多开发人员都采用了懒惰的方式而只是做fwrite了什么,而不是逐字节地选择数字.当机器升级到更长的字长时,一切都崩溃了.所以typedef很容易解决这个问题.

如果性能是一个问题,因为它通常是当时的,int保证是机器最快的自然尺寸,但如果你需要32位,并且int比这短,你就有翻车的危险.

在C语言中,sizeof()不应该在预处理器阶段解决,这使事情变得复杂,因为你无法做到这一点#if sizeof(int) == 4.

就个人而言,一些基本原理也只是从汇编语言的心态工作,不是不愿意抽象出什么样的概念short,int并且long是.那时候,汇编程序经常在C中使用.

如今,有很多非二进制文件格式,JSON,XML等,二进制表示是什么并不重要.同样,许多流行的平台已经确定了32位int或更长时间,这通常足以满足大多数用途,因此翻转的问题较少.

  • "大多数平台已经确定了32位或更大的" - >嗯,每年至少有100万个嵌入式进程(2016)使用16位`int`.C在那里很受欢迎. (5认同)

Joh*_*ode 5

C是20世纪70年代早期的产品,当时计算生态系统非常不同.而不是数百万台计算机都通过扩展网络相互通信,全世界可能有十万个系统,每个系统运行一些单片应用程序,系统之间几乎没有通信.您不能假设任何两个体系结构具有相同的字大小,或以相同的方式表示有符号整数.市场仍然很小,以至于没有任何需要标准化,计算机之间没有相互交谈(很多),也没有人谈论可移植性.

如果是这样,程序员如何期望使用C整数类型?

如果您想编写最大可移植代码,那么您不会假设超出标准保证的任何内容.在这种情况下int,这意味着你没有假设它可以表示范围之外的任何东西[-32767,32767],你也没有假设它将以2的补码表示,你也没有假设它是一个特定的宽度(它可能更宽)超过16位,但如果它包含任何填充位,则仍然只表示16位范围).

如果您不关心可移植性,或者您正在做一些本质上不可移植的东西(通常情况下有点麻烦),那么您使用的任何类型都符合您的要求.

我做的主要是高级应用程序编程,所以我不太担心表示而不是关于范围.即便如此,我偶尔也需要深入研究二进制表示,它总是让我陷入困境.我记得在90年代早期编写了一些必须在经典MacOS,Windows 3.1和Solaris上运行的代码.我为32位掩码创建了一堆枚举常量,它在Mac和Unix机器上运行良好,但无法在Windows机器上编译,因为在Windows int上只有16位宽.