我应该在 32/64 位机器上使用 stdint.h 整数类型吗?
Should I use the stdint.h integer types on 32/64 bit machines?
关于常规的 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_t 会比使用更大的整数(例如 int32_t 慢吗?
2) 如果我只需要一个到 运行 的 for 循环 10 次,是否可以使用可以处理它的最小整数而不是典型的 32 位整数?
for (int8_t i = 0; i < 10; i++) {
}
3) 每当我使用一个我知道永远不会为负的整数时,即使我不需要提供的额外范围,也可以更喜欢使用无符号版本吗?
// instead of the one above
for (uint8_t i = 0; i < 10; i++) {
}
4) 对 stdint.h
中包含的类型使用 typedef 是否安全
typedef int32_t signed_32_int;
typedef uint32_t unsigned_32_int;
编辑:两个答案都一样好,我真的不能偏向一个,所以我只选择了代表较低的回答者
Can using a smaller integer such as int16_t be slower than something higher such as int32_t?
是的。有些 CPU 没有专用的 16 位算术指令; 16 位整数的算术运算必须用如下指令序列模拟:
r1 = r2 + r3
r1 = r1 & 0xffff
同样的原则适用于 8 位类型。
在<stdint.h>
中使用"fast"整数类型来避免这种情况——例如,int_fast16_t
会给你一个至少[=39]的整数=] 16 位宽,但如果 16 位类型不是最佳的,可能会更宽。
If I needed a for loop to run just 10 times, is it ok to use the smallest integer that can handle it instead of the typical 32 bit integer?
别打扰了;只需使用 int
。使用较窄的类型实际上并不会节省任何 space,如果您决定将迭代次数增加到超过 127 次而忘记循环变量使用的是较窄的类型,则可能会导致问题出现。
Whenever I use an integer that I know will never be negative is it ok to prefer using the unsigned version even if I do not need the extra range in provides?
最好避免。某些 C 习语不能正确处理无符号整数;例如,您不能编写以下形式的循环:
for (i = 100; i >= 0; i--) { … }
如果i
是无符号类型,因为i >= 0
永远为真!
Is it safe to use a typedef for the types included from stdint.h
从技术角度来看是安全的,但它会惹恼其他必须使用您的代码的开发人员。
习惯 <stdint.h>
的名字。它们是标准化的并且相当容易输入。
1) Can using a smaller integer such as int16_t be slower than something higher such as int32_t?
是的,它可能会更慢。请改用 int_fast16_t
。根据需要分析代码。性能非常依赖于实现。 int16_t
的一个主要好处是它的小而明确的大小(也必须是 2 的补码)用于结构和数组,而不是速度。
The typedef name int_fastN_t
designates the fastest signed integer type with a width of at least N. C11 §7.20.1.3 2
2) If I needed a for loop to run just 10 times, is it ok to use the smallest integer that can handle it instead of the typical 32 bit integer?
是的,但代码和速度的节省值得怀疑。建议改为 int
。发出的代码在 speed/size 中往往是最佳的,具有本机 int
大小。
3) Whenever I use an integer that I know will never be negative is it OK to prefer using the unsigned version even if I do not need the extra range in provides?
当数学严格无符号时(例如使用 size_t
的数组索引),使用一些无符号类型是首选,但代码需要注意粗心的应用程序,如
for (unsigned i = 10 ; i >= 0; i--) // infinite loop
4) Is it safe to use a typedef for the types included from stdint.h
几乎总是。 int16_t
之类的类型是可选的。最大可移植性使用所需的类型 uint_least16_t
和 uint_fast16_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.
}
是的。此外,POSIX 提供 inttypes.h
扩展 stdint.h
一些有用的函数和宏。
关于常规的 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_t 会比使用更大的整数(例如 int32_t 慢吗?
2) 如果我只需要一个到 运行 的 for 循环 10 次,是否可以使用可以处理它的最小整数而不是典型的 32 位整数?
for (int8_t i = 0; i < 10; i++) {
}
3) 每当我使用一个我知道永远不会为负的整数时,即使我不需要提供的额外范围,也可以更喜欢使用无符号版本吗?
// instead of the one above
for (uint8_t i = 0; i < 10; i++) {
}
4) 对 stdint.h
中包含的类型使用 typedef 是否安全typedef int32_t signed_32_int;
typedef uint32_t unsigned_32_int;
编辑:两个答案都一样好,我真的不能偏向一个,所以我只选择了代表较低的回答者
Can using a smaller integer such as int16_t be slower than something higher such as int32_t?
是的。有些 CPU 没有专用的 16 位算术指令; 16 位整数的算术运算必须用如下指令序列模拟:
r1 = r2 + r3
r1 = r1 & 0xffff
同样的原则适用于 8 位类型。
在<stdint.h>
中使用"fast"整数类型来避免这种情况——例如,int_fast16_t
会给你一个至少[=39]的整数=] 16 位宽,但如果 16 位类型不是最佳的,可能会更宽。
If I needed a for loop to run just 10 times, is it ok to use the smallest integer that can handle it instead of the typical 32 bit integer?
别打扰了;只需使用 int
。使用较窄的类型实际上并不会节省任何 space,如果您决定将迭代次数增加到超过 127 次而忘记循环变量使用的是较窄的类型,则可能会导致问题出现。
Whenever I use an integer that I know will never be negative is it ok to prefer using the unsigned version even if I do not need the extra range in provides?
最好避免。某些 C 习语不能正确处理无符号整数;例如,您不能编写以下形式的循环:
for (i = 100; i >= 0; i--) { … }
如果i
是无符号类型,因为i >= 0
永远为真!
Is it safe to use a typedef for the types included from stdint.h
从技术角度来看是安全的,但它会惹恼其他必须使用您的代码的开发人员。
习惯 <stdint.h>
的名字。它们是标准化的并且相当容易输入。
1) Can using a smaller integer such as int16_t be slower than something higher such as int32_t?
是的,它可能会更慢。请改用 int_fast16_t
。根据需要分析代码。性能非常依赖于实现。 int16_t
的一个主要好处是它的小而明确的大小(也必须是 2 的补码)用于结构和数组,而不是速度。
The typedef name
int_fastN_t
designates the fastest signed integer type with a width of at least N. C11 §7.20.1.3 2
2) If I needed a for loop to run just 10 times, is it ok to use the smallest integer that can handle it instead of the typical 32 bit integer?
是的,但代码和速度的节省值得怀疑。建议改为 int
。发出的代码在 speed/size 中往往是最佳的,具有本机 int
大小。
3) Whenever I use an integer that I know will never be negative is it OK to prefer using the unsigned version even if I do not need the extra range in provides?
当数学严格无符号时(例如使用 size_t
的数组索引),使用一些无符号类型是首选,但代码需要注意粗心的应用程序,如
for (unsigned i = 10 ; i >= 0; i--) // infinite loop
4) Is it safe to use a typedef for the types included from stdint.h
几乎总是。 int16_t
之类的类型是可选的。最大可移植性使用所需的类型 uint_least16_t
和 uint_fast16_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. }
是的。此外,POSIX 提供
inttypes.h
扩展stdint.h
一些有用的函数和宏。