53

我已经知道,stdint当您需要特定的可变大小以实现平台之间的可移植性时,这已经习惯了。我现在真的没有这样的问题,但是除了上面已经显示的事实之外,使用它的缺点和优点是什么?

在 stackoverflow 和其他网站上寻找这个,我发现了 2 个关于主题的链接:

如果您希望了解更多有关此标头可移植性的主要原因,这两个链接特别有用。但对我来说,我最喜欢它的是我认为uint8_t它比unsigned char(例如用于存储 RBG 通道值)更干净,int32_t看起来比简单的更有意义int,等等。

stdint所以,我的问题是,除了便携性之外,使用的优缺点到底是什么?我应该只在代码的某些特定部分还是在任何地方使用它?如果无处不在,我怎样才能使用像atoi(),strtok()等这样的功能呢?

谢谢!

4

4 回答 4

80

优点

int使用定义明确的类型可以使代码更容易和更安全地移植,因为例如当一台机器解释为 16 位而另一台机器解释为 32 位时,您不会有任何意外。使用 stdint.h,你输入的就是你得到的。

使用intetc 也使得很难检测到危险类型的促销。

另一个优点是,通过使用int8_t而不是char,你知道你总是得到一个有符号的 8 位变量。char可以有符号或无符号,它是实现定义的行为,并且在编译器之间有所不同。因此,在char应该可移植的代码中使用默认值是很危险的。

如果你想给编译器提示一个变量应该被优化,你可以使用uint_fastx_twhich 告诉编译器使用最快的整数类型,至少和'x'一样大。大多数时候这无关紧要,编译器足够聪明,可以优化类型大小,无论您输入了什么。在序列点之间,编译器可以隐式将类型更改为指定以外的类型,只要它不影响结果。

缺点

没有任何。


参考:MISRA-C:2004 规则 6.3。“应使用指示大小和符号的typedef代替基本类型”。

编辑:删除不正确的例子。

于 2012-03-23T10:13:49.953 回答
19

使用uint8_t而不是unsigned char(除了审美偏好)的唯一原因是如果您想记录您的程序需要char正好是 8 位。uint8_t存在当且仅当CHAR_BIT==8,根据 C 标准的要求。

其余的intX_tuintX_t类型在以下情况下很有用:

  • 读/写磁盘/网络(但你还必须使用字节序转换功能)
  • 当您希望在精确截止时进行无符号环绕行为(但这可以通过操作&员更便携地完成)。
  • 当您控制结构的确切布局时,因为您需要确保不存在填充(例如,出于memcmp散列目的)。

另一方面,uint_least8_t, etc. 类型在您想要避免使用浪费的大或慢类型但需要确保您可以存储一定量级的值的任何地方都很有用。例如,虽然long long至少是 64 位,但在某些机器上可能是 128 位,当您需要的只是可以存储 64 位数字的类型时使用它在此类机器上会非常浪费。int_least64_t解决问题。

我会[u]int_fastX_t完全避免使用这些类型,因为它们有时会在给定的机器上发生变化(破坏 ABI),而且定义通常是错误的。例如,在 x86_64 上,64 位整数类型被认为是 16、32 和 64 位值的“快速”类型,但加法、减法和乘法的速度完全相同,无论您使用 32-位或 64 位值,对于大于必要的类型,除法几乎肯定会更慢,即使它们的速度相同,您使用两倍的内存也没有任何好处。

最后,请注意,int32_t当计数器不是本机整数大小时,一些答案关于使用计数器效率低下的论点在技术上大多是正确的,但与更正代码无关。除非您在计算最大计数受您控制的少量事物,或者计数可能是天文数字的某些外部(不在程序内存中)事物,否则计数的正确类型几乎总是size_t. 这就是所有标准 C 函数都size_t用于计数的原因。除非您有充分的理由,否则不要考虑使用其他任何东西。

于 2012-03-23T12:13:22.980 回答
8

缺点

intC 语言不指定orlong等​​的大小的主要原因是为了计算效率。每种架构都有一个自然的、最有效的大小,设计人员特别授权并希望编译器实现者使用自然的本机数据大小数据来提高速度和代码大小效率。

在过去的几年里,与其他机器的通信并不是主要的问题——大多数程序都是机器本地的——所以每个数据类型的大小的可预测性是无关紧要的。

坚持一个特定的架构使用特定的大小int来计算是一个非常糟糕的主意,即使它似乎使其他事情变得更容易。

在某种程度上,多亏了 XML 及其兄弟,数据类型的大小不再是一个大问题。在机器之间传送特定于机器的二进制结构再次是例外而不是规则。

于 2012-03-23T06:24:31.470 回答
6

我使用 stdint 类型仅出于一个原因,当我保存在内存中的数据将以二进制形式存储在磁盘/网络/描述符上时。您只需要解决 little-endian/big-endian 问题,但相对容易克服

使用 stdint的明显原因是当代码与大小无关时,在数学术语中,所有适用于有理整数的东西。如果您提供一个uint*_t版本,例如,qsort()*.

在这种情况下,我使用我自己的类型,这些类型源自size_t我懒惰的时候或平台上支持的最大无符号整数,而我不是。

编辑,因为我之前遇到过这个问题:
我认为值得注意的是,至少uint8_t,uint32_t并且uint64_t在 Solaris 2.5.1 中被破坏了。因此,为了获得最大的便携性,我仍然建议避免stdint.h(至少在未来几年内)。

于 2012-03-23T10:44:12.230 回答