我记得在某处读过最好使用整数作为循环计数器变量而不是char或short。如果是,为什么?它是否提供任何优化好处?
答案 0 :(得分:14)
通常,编译器会使int
成为放入CPU通用寄存器的好大小。这通常会导致快速访问。
当然没有任何保证。编译器可以自由地做很多事情,包括我猜测,将一些使用char
的代码推广到更大的类型。所以差异可能不重要。
真的,对于 编译器的答案,您应该查看它输出的程序集。
答案 1 :(得分:8)
在具有4个字节(int)的32位架构操作中,变量通常更快。这主要是由于寄存器的大小和内存对齐。在64位架构中,它将(应该)自动生成64位整数。
答案 2 :(得分:4)
Alexey *是对的,使用与架构宽度相同的类型(即32位系统的int32)通常会更快
另外,如果你使用char,即
for(char i=0;i<max;++i)
你(或同事)在一个月的时间内回到代码并将最大值更改为高位,导致溢出和恼人的错误的可能性很小;)
萨姆
*和其他在我写这篇文章时回答的人!
答案 3 :(得分:3)
int
类型通常可以说是您平台上实现最快的整数类型,因此应该是默认选择。
来自K&amp; R,第2版,p。 36:
int
:一个整数,通常反映主机上整数的自然大小。
答案 4 :(得分:2)
将size_t
类型用于循环计数器会更好。它将扩展到64位。
答案 5 :(得分:2)
有没有注意到C标准对整数大小的影响有多大?这一事实促使设备驱动程序工程师和从事通信协议工作的人员感到头晕目眩,因为他们认为该语言应该清楚地定义对象的大小。
C表示int
是实现架构的自然大小。这意味着它将至少与任何其他尺寸一样有效地处理。采用x86架构:32位程序中使用的short
(16位整数)包含执行额外“大小覆盖”修改的指令。所以代码有更多的字节,但通常没有性能损失。除非额外的字节导致缓存行溢出....
char
计数器的x86生成代码通常包括增量后的屏蔽,以确保它保持8位。似乎使用较小的变量会更小更紧凑,但x86和其他几个常见CPU的情况并非如此。
答案 6 :(得分:2)
担心在担心这些问题之前让你的循环正确。通过更改int
,char
或{之间的循环计数器类型,您更有可能在循环边界中出现一个一个错误的错误,而不是速度或代码大小的可测量差异。 {1}}。所以首先要担心正确性。
那就是说,默认使用short
或int
,除非你有理由不这样做 - 但是我这样说是因为你不太可能需要担心溢出或者更大输入不是因为它可能更快(即使它可能)。
答案 7 :(得分:1)
在某些情况下,char
s(甚至short
s)的溢出问题将产生非终止循环。
答案 8 :(得分:1)
这实际上取决于您为代码编写的平台。最好使用的类型是将其与您的平台相匹配。即,如果您正在编写一个简单的8位微代码,也许使用uint8_t比使用uint16_t更好。
答案 9 :(得分:1)
通常,int是循环的正确选择。它可能有两个原因:
所以,是的,根据您的架构,您可能需要考虑有多大的整数。但通常你不会。
答案 10 :(得分:0)
这实际上取决于你的循环在做什么。以此循环为例:
typedef struct _SomeData
{
/* some data here */
} SomeData;
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
int i;
for (i = 0 ; i < number_of_elements ; ++i)
{
DoSomethingWithData (&array_of_data [i]);
}
}
有些编译器会很好地优化上述内容。但是一些编译器,特别是针对利基嵌入式微处理器的编译器,将产生可怕的无效代码。它可以重写为:
void SomeFunction (SomeData *array_of_data, int number_of_elements)
{
SomeData *current = array_of_data, *end = &array_of_data [number_of_elements];
while (current < end)
{
DoSomethingWithData (current++);
}
}
根本不使用整数,并且无论编译器如何都更有可能产生良好的输出(现代编译器可能会将整数版本优化为类似上面的内容)。
因此,循环并不总是需要整数,最好的优化总是不做必要的事情。但是,如果循环明确需要整数,则int类型通常会提供最佳结果。
当然,您必须始终使用分析器来确定代码的性能以及更改类型是否有所不同。