2017-04-11 81 views
3

有一点让我对常规c整数声明感到困惑的是,他们的名字很奇怪,“long long”是最糟糕的。我只为32位和64位计算机构建,所以我不一定需要库提供的可移植性,但是我喜欢每种类型的名称都是一个长度相似的单个词,并且大小没有歧义。我应该在32/64位机器上使用stdint.h整数类型吗?

// 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)是否可以安全使用typedef的类型从stdint.h包括

typedef int32_t signed_32_int; 
typedef uint32_t unsigned_32_int; 

编辑:两个答案都一样好,我真的不能向一个瘦,所以我只是选择较低的代表回答者

+1

你有看看http://stackoverflow.com/questions/9834747/reasons-to-use-or-not-stdint? – Nic

+1

[使用(或不)stdint的原因]的可能重复(http://stackoverflow.com/questions/9834747/reasons-to-use-or-not-stdint) –

+0

他们是类似的,但我有一些具体问题如何实施那些在那篇文章中没有明确回答的文章。同样来自该帖子的最佳答案也会让你听起来像固定类型不会出错,但根据下面两个答案已经解决的问题,这不一定是正确的。 – YeOldeBitwise

回答

3

1)可以使用一个较小的整数,如int16_t比像int32_t这样的高一些的东西慢一些?

是的,它可以更慢。改为使用int_fast16_t。根据需要对代码进行剖析。性能非常依赖于实施。 int16_t的一个主要好处是其结构和阵列中使用的小尺寸(也必须是2的补码),而不是速度。

typedef名int_fastN_t表示具有至少Ñ宽度最快符号整数类型。 C11§7.20.1.32


2)如果我需要一个循环,仅运行10次,是正常使用可以处理它,而不是典型的32位整数的最小整数?

是的,但代码和速度的节省是值得怀疑的。建议使用int。发送的代码在速度/大小方面往往是最佳的,其大小为原生int


3)每当我使用一个整数,我知道永远都不会是负的就OK了喜欢使用无符号的版本,即使我并不需要额外的范围内提供?

使用一些无符号类型是优选的,当数学严格无符号(如与size_t数组索引),但代码需要观看粗心应用像

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

4)对于stdint.h中包含的类型,使用typedef是否安全?

几乎总是如此。像int16_t这样的类型是可选的。最大可移植性使用所需的类型uint_least16_tuint_fast16_t以使代码能够在使用位宽度为9,18等的罕见平台上运行

+0

关于可选项:“这些类型是可选的*但是,如果实现提供宽度为8,16,32或64位的整数类型,没有填充位,并且(对于带符号的类型)有二进制补码表示,它应该定义相应的typedef名称。“ (第7.20.1.1/3号N1570“准C11”)。我认为** **几乎可以匹配任何实现...(现在) –

3

可以使用较小的整数,如int16_t比某些更高的如int32_t更慢?

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

r1 = r2 + r3 
r1 = r1 & 0xffff 

相同的原理适用于8位类型。

使用“快”整数类型<stdint.h>避免这种情况 - 例如,int_fast16_t会给你一个整数宽至少 16位,但如果16位类型非最佳可能更宽。

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

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

每当我使用一个我知道永远不会消极的整数时,即使我不需要提供额外范围,也可以使用未签名版本吗?

最好避免。某些C语言在无符号整数上无法正常工作;例如,你可以不写形式的循环:

for (i = 100; i >= 0; i--) { … } 

如果i是一个无符号的类型,因为i >= 0永远是真实的!

是否可以安全使用typedef的类型从stdint.h

安全从技术角度包括在内,但它会激怒其他开发商谁与你的代码工作。

习惯了<stdint.h>的名字。它们是标准化的,并且相当容易输入。

+0

“使用较窄的类型[... ]“ - 并且使用比处理器的寄存器大小更宽的类型甚至可以减慢程序的速度...”一般只使用int“,但有一个例外:如果您对可能不适合int的较大值进行操作,在这种情况下更喜欢快速类型。 “最好避免” - 再次例外:for(i = 0; i Aconcagua

1
  1. 绝对可能,是的。在我的笔记本电脑(英特尔的Haswell),在计算了微基准上下介于0和65535两个寄存器2十亿倍,这需要定时

    1.313660150s - ax dx (16-bit) 
    1.312484805s - eax edx (32-bit) 
    1.312270238s - rax rdx (64-bit) 
    

    小写状态,但重复的差异。 (我在汇编中写了基准,因为C编译器可能会将其优化为不同的寄存器大小。)

  2. 它会工作,但如果更改边界和C编译器,则必须保持最新无论如何,它可能会优化它到相同的汇编代码。

  3. 只要它是正确的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. 
        } 
    
  4. 是的。此外,POSIX提供了inttypes.h,它将stdint.h扩展为一些有用的函数和宏。

相关问题