这主要用于手动微优化,其中大小并不重要,但您怀疑较大的整数类型会导致更快的代码。在编写可广泛移植的代码时,它也有它的用途。 例如,如果您开发的算术代码至少需要16位,并且应该在16位和32位CPU上运行。在int16_t上进行运算可能不是最佳的,因为有限的指令,对齐等。但是如果你在int_fast16_t上做算术,那么它就不会像32位算术那样不必要地增加16位的负担,因为在那个目标上类型仍然是16位。但与此同时,它仍然允许32苦选择一个更大的类型,如果这给更好的性能。 另一个优点是int_fastn_t对于2的补码目标的 all C编译器是强制性的,包括独立的实现(嵌入式系统,古怪的DSP编译器等)。 相对于intn_t的缺点是int_fastn_t * 不是 * 固定的宽度,确切的宽度很重要,并且使用int_fastn_t强制执行手动的速度超过大小优化,我们通常可以让选择的编译器选项来决定。
*uint_fastn_t
与int_fastn_t相同的优点/缺点,但也适用于按位算术。
*int_leastn_t / uint_leastn_t
这些都是非常特殊用途的古怪类型。基本上,你会说“我需要变量至少是 n 位,但除此之外,你可以随心所欲”。与fast类型不同,这给了编译器更大的自由,可以选择大小或速度优化,也可以根本不优化。 当您需要优化大小并同时在多个目标之间进行移植时,这些类型的保存并没有太多用处。例如,在我上面的16位与32位CPU的例子中,int_least16_t在16位CPU上仍然是16位,但在32位CPU上,编译器可能会选择将其保留为16位,以防给予大小上的好处。 例如,支持VLE编码的32位PowerPC(基本上:如果可能的话,使用16位指令)可能会受益于least类型,因为无论机器码是否使用VLE,您都可以保持C代码不变。
3条答案
按热度按时间p1tboqfb1#
size_t
(unsigned 类型)来调整数组大小和索引。(u)int_fastN_t
,除非确实需要。也许当一个狭窄的类型是必要的,但速度是关键。它们不值得一时兴起使用。fast
类型要求文档证明其使用。...fast..
作为位域。(u)int_fastN_t
很少有用。(u)int_fastN_t/(u)int_leastN_t
始终可用,并且与 * 可选 *(u)intN_t
相比,在可移植性方面略有优势。int/unsigned
自C语言诞生以来就一直可用。请记住, 快速 * 类型是一种妥协。 快速 * 并不总是在所有用例中最快。*
x6yk4ghg2#
这里有一些因素要考虑,使您的选择:
理由:越简单越好。
int
的范围,请使用更大的类型:long
或int64_t
.使用int_fastN_t
或int_leastN_t
会使代码更难阅读,并且在大多数体系结构上不会产生差异。6ojccjat3#
*
int
这种类型几乎只有一个好处,那就是向后兼容非关键代码,其中整数限制/大小无关紧要。你几乎不应该使用它,除非你被老C90的向后兼容性问题所困扰。
*
unsigned int
与
int
相同的参数-此类型主要用于旧代码中,其中整数大小无关紧要。但是它稍微更有用一些,因为它可以被视为一种安全的通用类型,可以在受到隐式整数提升的表达式中使用。如果你使用unsigned int
或者强制转换一个操作数,那么它就不再受到整数提升,默认参数提升等的影响。您也可以在按位算术中安全地使用unsigned int
,其中应避免使用int
。此外,像
short
,signed char
等小整数类型也是同样危险的,因为它们会受到隐式提升,由于整数提升而导致的潜在符号变化,由于提升而隐藏溢出/回绕的可能性等。*
intn_t
(其中 n 对应于目标的字大小)与
int
相比,intn_t
具有便携和固定宽度的巨大优势。但前提是 n 足够大,不会使操作数成为整数提升的对象,例如32/64位计算机上的int32_t
。intn_t
还有一个很大的优点,就是可以保证是2的补码形式,这对于int
来说是不能保证的(直到C23的发布)。一个小细节是,除非目标支持
intn_t
,否则不能保证它得到支持。这并不适用于99%的真实系统,只适用于一些具有16位字节的古怪DSP CPU。值得注意的是,
intn_t
应该 * 仅 * 用于实际需要有符号数字的地方。如果你不需要带符号的数字,那么就使用uintn_t
。*
uintn_t
intn_t
的所有好处都是相同的,但还有另一个好处,即它也可以安全地用于按位算术。使其成为最通用的整数类型。*
int_fastn_t
这主要用于手动微优化,其中大小并不重要,但您怀疑较大的整数类型会导致更快的代码。在编写可广泛移植的代码时,它也有它的用途。
例如,如果您开发的算术代码至少需要16位,并且应该在16位和32位CPU上运行。在
int16_t
上进行运算可能不是最佳的,因为有限的指令,对齐等。但是如果你在int_fast16_t
上做算术,那么它就不会像32位算术那样不必要地增加16位的负担,因为在那个目标上类型仍然是16位。但与此同时,它仍然允许32苦选择一个更大的类型,如果这给更好的性能。另一个优点是
int_fastn_t
对于2的补码目标的 all C编译器是强制性的,包括独立的实现(嵌入式系统,古怪的DSP编译器等)。相对于
intn_t
的缺点是int_fastn_t
* 不是 * 固定的宽度,确切的宽度很重要,并且使用int_fastn_t
强制执行手动的速度超过大小优化,我们通常可以让选择的编译器选项来决定。*
uint_fastn_t
与
int_fastn_t
相同的优点/缺点,但也适用于按位算术。*
int_leastn_t
/uint_leastn_t
这些都是非常特殊用途的古怪类型。基本上,你会说“我需要变量至少是 n 位,但除此之外,你可以随心所欲”。与
fast
类型不同,这给了编译器更大的自由,可以选择大小或速度优化,也可以根本不优化。当您需要优化大小并同时在多个目标之间进行移植时,这些类型的保存并没有太多用处。例如,在我上面的16位与32位CPU的例子中,
int_least16_t
在16位CPU上仍然是16位,但在32位CPU上,编译器可能会选择将其保留为16位,以防给予大小上的好处。例如,支持VLE编码的32位PowerPC(基本上:如果可能的话,使用16位指令)可能会受益于
least
类型,因为无论机器码是否使用VLE,您都可以保持C代码不变。拾荒者程序
我拼凑了一个TL;整型选择器。根据#define调整true/false,让它选择合适的整数类型。
使用gcc 13.2 -std= c2 x进行测试。https://godbolt.org/z/zz9GTf35M