使用(或不使用)stdint的原因
我已经知道,当你需要特定的variables大小来实现平台之间的可移植性时,stdint已经习惯了,现在我真的没有这个问题,但是除了上面已经显示的事实之外,使用它的缺点和优点是什么呢?
在stackoverflow和其他网站上find它,我发现了2个关于主题的链接:
-
1 – 这个讨论stdint的可移植性。
-
2 – 这个更关心uint8_t。
这两个链接是非常重要的,特别是要更多地了解这个头的主要原因是可移植性,但对于我来说,我最喜欢的是,我认为uint8_t比unsigned char更清晰(例如用于存储RBG通道值) ,int32_t比简单的int看起来更有意义,等等
所以,我的问题是,除了可移植性之外,究竟是什么缺点,特别是使用stdint的优点,我是否应该只在代码的某些特定部分或其他地方使用它? 如果到处都是,用户如何使用atoi,strtok等function呢?
谢谢!
优点
使用定义良好的types使得代码更容易和更安全地移植,例如,当一台机器将int
解释为16位而另一台机器解释为32位时,您不会感到意外。 用stdint.h,你input的是你所得到的。
使用int
等也使得很难检测危险types的促销活动。
另一个好处是通过使用int8_t
而不是char
,你知道你总是得到一个有符号的8位variables。 char
可以是有符号或无符号的,它是实现定义的行为,在编译器之间有所不同。 因此,默认的char
在应该是可移植的代码中使用是非常危险的。
如果你想让编译器提示variables应该被优化,你可以使用uint_fastx_t
来告诉编译器使用尽可能快的整数types,至less和'x'一样大。 大多数情况下,这并不重要,编译器足够聪明,可以对字符大小进行优化,而不pipe您input的是什么。在序列点之间,编译器可以隐式地将types更改为另一个types,只要不影响结果。
缺点
没有。
参考:MISRA-C:2004规则6.3“应使用表示大小和符号的types定义来代替基本types”。
编辑:删除不正确的示例。
使用uint8_t
而不是unsigned char
(除了审美偏好)的唯一原因是如果你想logging你的程序需要char
恰好是8位。 根据C标准的要求,当且仅当CHAR_BIT==8
, uint8_t
存在。
在以下情况下, intX_t
和uintX_t
types的其余部分很有用:
- 读/写磁盘/networking(但是你也必须使用endian转换function)
- 当你想要在一个确切的截止时使用无符号的环绕行为(但是这可以通过
&
运算符来更方便地完成)。 - 当你控制一个结构的确切的布局,因为你需要确保没有填充存在(例如,为
memcmp
或散列的目的)。
另一方面, uint_least8_t
等types在你想要避免浪费大或慢types的任何地方是有用的,但是需要确保你可以存储一定数量的值。 例如, long long
至less为64位,在某些机器上可能是128位,而当你需要的只是一个可以存储64位数的types时,在这样的机器上是非常浪费的。 int_least64_t
解决了这个问题。
我会避免完全使用[u]int_fastX_t
types,因为它们有时在给定的机器上发生了变化 (中断ABI),并且定义通常是错误的。 例如,在x86_64上,对于16位,32位和64位的值,64位整数types被认为是“快速”types的,但是加法,减法和乘法的速度是完全相同的, bit或64-bit值,除非需要更大的分区,分区几乎肯定会变慢,即使它们的速度相同,也会使用两倍的内存。
最后,请注意,一些答案已经提出了关于使用int32_t
作为计数器时,如果它不是本地整数大小,在技术上大部分都是正确的,但这与正确的代码无关。 除非你正在计算一些数量最less的东西在你的控制之下,或者一些外部的(而不是你的程序的内存),那么计数可能是天文数字,正确的计数types几乎总是size_t
。 这就是为什么所有的标准C函数都使用size_t
来计数的原因。 除非你有很好的理由,否则不要考虑使用其他的东西。
缺点
C语言没有指定int
或long
等的大小的主要原因是为了计算效率。 每个架构都有一个自然的,最有效的大小,而且devise人员专门赋予了编译器实现者权力,使其能够使用自然的本地数据大小数据来提高速度和代码大小的效率。
在过去的几年中,与其他机器的通信并不是主要的关注点 – 大多数程序都是机器本地的 – 所以每种数据types的可预测性都不受关注。
坚持一个特定的架构使用一个特定的大小int
来计算是一个非常糟糕的主意 ,即使它似乎使其他事情更容易。
在某种程度上,由于XML和它的同仁们,数据types的大小已经不再是一个问题了。 从一台机器到另一台机器运输特定于机器的二进制结构再次是例外而不是规则。
我使用stdinttypes的原因只有一个,当我在内存中保存的数据将以二进制forms在磁盘/networking/描述符上。 你只需要对付小端/大端问题,但这相对容易克服 。
不使用stdint的明显原因是代码大小无关,用math术语表示所有对有理整数有效的东西。 如果你为uint*_t
的每个扩展提供了一个uint*_t
版本的,比如说qsort()
,那么将会产生丑陋的代码重复。
在这种情况下,我使用自己的types,当我懒时,从size_t
派生出来,或者当我没有时,在平台上支持最大的无符号整数。
编辑,因为我更早遇到这个问题:
我认为值得注意的是,至lessuint8_t
, uint32_t
和uint64_t
在Solaris 2.5.1中被破坏了。 所以为了最大的便携性,我仍然build议避免stdint.h
(至less在未来几年)。