C 我应该在32/64位机器上使用stdint.h整数类型吗?

C 我应该在32/64位机器上使用stdint.h整数类型吗?,c,integer,typedef,stdint,C,Integer,Typedef,Stdint,关于常规的c整数声明,有一件事让我感到困扰,那就是它们的名字很奇怪,“long-long”是最糟糕的。我只为32位和64位机器构建,所以我不一定需要库提供的可移植性,但是我喜欢每种类型的名称都是一个长度相似的单词,大小没有歧义 // multiple word types are hard to read // long integers can be 32 or 64 bits depending on the machine unsigned long int foo = 64; long

关于常规的c整数声明,有一件事让我感到困扰,那就是它们的名字很奇怪,“long-long”是最糟糕的。我只为32位和64位机器构建,所以我不一定需要库提供的可移植性,但是我喜欢每种类型的名称都是一个长度相似的单词,大小没有歧义

// multiple word types are hard to read
// long integers can be 32 or 64 bits depending on the machine

unsigned long int foo = 64;
long int bar = -64;

// easy to read
// no ambiguity

uint64_t foo = 64;
int64_t bar = -64;
在32位和64位计算机上:

1) 使用较小的整数(如int16)是否比使用较高的整数(如int32)慢

2) 如果我需要一个for循环只运行10次,那么可以使用能够处理它的最小整数而不是典型的32位整数吗

for (int8_t i = 0; i < 10; i++) {

}
编辑:两个答案都一样好,我不能真正倾向于一个,所以我选择了代表性较低的答案

使用较小的整数(如int16)是否比使用较高的整数(如int32)慢

对。有些CPU没有专用的16位算术指令;16位整数上的算术运算必须使用以下指令序列进行仿真:

r1 = r2 + r3
r1 = r1 & 0xffff
同样的原理也适用于8位类型

使用
中的“快速”整数类型来避免这种情况——例如,
int\u fast16\u t
将为您提供一个至少16位宽的整数,但如果16位类型是非最佳的,则可能会更宽

如果我需要一个for循环只运行10次,那么可以使用能够处理它的最小整数而不是典型的32位整数吗

for (int8_t i = 0; i < 10; i++) {

}
不用麻烦了;只需使用
int
。使用更窄的类型实际上不会节省任何空间,如果您决定将迭代次数增加到127次以上,并且忘记循环变量使用的是窄类型,则可能会导致后续问题

每当我使用一个我知道永远不会为负的整数时,即使我不需要额外的范围,也可以选择使用无符号版本吗

// instead of the one above
for (uint8_t i = 0; i < 10; i++) {

}
最好避免。某些C语言习惯用法不能正确处理无符号整数;例如,您不能编写以下表单的循环:

for (i = 100; i >= 0; i--) { … }
如果
i
是无符号类型,因为
i>=0
将始终为真

对stdint.h中包含的类型使用typedef安全吗

typedef int32_t signed_32_int;
typedef uint32_t unsigned_32_int;
从技术角度来看是安全的,但它会让其他不得不使用您的代码的开发人员感到烦恼

习惯
名称。它们是标准化的,而且很容易打字

1) 使用较小的整数(如int16)是否比使用较高的整数(如int32)慢

是的,它可以慢一点。改用
int\u fast16\t
。根据需要分析代码。性能非常依赖于实现。
int16\u t
的一个主要优点是,它的大小很小,定义很好(也必须是2的补码),就像在结构和数组中使用的那样,而不是速度

typedef name
int_fastN_t
指定宽度至少为N.C11§7.20.1.3 2的最快有符号整数类型


2) 如果我需要一个for循环只运行10次,那么可以使用能够处理它的最小整数而不是典型的32位整数吗

for (int8_t i = 0; i < 10; i++) {

}
是的,但是在代码和速度上的节省是值得怀疑的。建议改为
int
。使用本机
int
size,发出的代码在速度/大小方面趋于最佳


3) 每当我使用一个我知道永远不会为负的整数时,即使我不需要额外的范围,也可以选择使用无符号版本吗

// instead of the one above
for (uint8_t i = 0; i < 10; i++) {

}
当数学是严格无符号的(例如使用
size\t
的数组索引)时,最好使用一些无符号类型,但代码需要注意粗心的应用程序,如

for (unsigned i = 10 ; i >= 0; i--) // infinite loop

4) 对stdint.h中包含的类型使用typedef安全吗

typedef int32_t signed_32_int;
typedef uint32_t unsigned_32_int;
几乎总是这样。像
int16\t
这样的类型是可选的。最大可移植性使用所需的类型
uint\u least16\u t
uint\u fast16\u t
,以便代码在使用比特宽度(如9、18等)的罕见平台上运行

  • 绝对有可能,是的。在我的笔记本电脑(Intel Haswell)上,在一个微基准上,两个寄存器上的上下计数在0到65535之间20亿次,这需要

    1.313660150s - ax dx (16-bit)
    1.312484805s - eax edx (32-bit)
    1.312270238s - rax rdx (64-bit)
    
    时间上微小但可重复的差异。(我在汇编中编写了基准测试,因为C编译器可能会将其优化为不同的寄存器大小。)

  • 它可以工作,但是如果您更改了边界,您必须使它保持最新,并且C编译器可能会将其优化为相同的汇编代码

  • 只要它是正确的C,那就完全可以了。请记住,无符号溢出是定义的,而有符号溢出是未定义的,编译器会利用这一点进行优化。比如说,

    void foo(int start, int count) {
        for (int i = start; i < start + count; i++) {
            // With unsigned arithmetic, this will execute 0 times if
            // "start + count" overflows to a number smaller than "start".
            // With signed arithmetic, that may happen, or the compiler
            // may assume this loop always runs "count" times.
            // For defined behavior, avoid signed overflow.
        }
    
    void foo(整数开始,整数计数){
    对于(int i=start;i
  • 是的。此外,POSIX还提供了
    inttypes.h
    ,它用一些有用的函数和宏扩展了
    stdint.h


  • 你看了吗?可能的重复它们是相似的,但是我有一些关于如何实现它们的具体问题,在那篇文章中没有得到明确的回答。另外,那篇文章的顶部答案听起来像是固定类型不会出错,但根据下面的两个答案,这不一定是正确的e已经澄清了这一点。“使用更窄的类型[…]”——并且使用比处理器寄存器大小更宽的类型甚至会减慢程序的速度……”“只需使用int”一般来说,有一个例外:如果您对可能不适合int的大值进行操作,在这种情况下,人们可能更喜欢[…]快速[…]类型。“最好避免”