C++ 循环中的模与if语句

C++ 循环中的模与if语句,c++,c,C++,C,我有一个这样的循环: for(i = 0; i < arrayLength; i++) { result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]); *bitIndex %= 8; } for(i = 0; i < arrayLength; i++) { (*bitIndex)++; SETBIT(&result[i / 8], *bitIndex, array[i]);

我有一个这样的循环:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    *bitIndex %= 8;
}
for(i = 0; i < arrayLength; i++)
{
    (*bitIndex)++;
    SETBIT(&result[i / 8], *bitIndex, array[i]);
    *bitIndex %= 8;
}
(i=0;i { 结果[i/8]=SETBIT(结果[i/8],++(*bitIndex),数组[i]); *bitIndex%=8; } 我想知道如果我使用上述样式或此样式,性能方面有什么更好:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    if(*bitIndex == 8) *bitIndex = 0;
}
(i=0;i { 结果[i/8]=SETBIT(结果[i/8],++(*bitIndex),数组[i]); 如果(*bitIndex==8)*bitIndex=0; } 这是用C语言编写的,使用GCC进行编译,如有解释也将不胜感激


谢谢

老实说,它们之间的差别只有一小部分。但我相信第一种方式对于简单的阅读风格会稍微好一点。然而,这个问题涉及到性能,我仍然认为第一个问题对于编译器读取/计算更少的信息这一事实来说具有非常微小的优势

老实说,它们之间的差别只有一小部分。但我相信第一种方式对于简单的阅读风格会稍微好一点。然而,这个问题涉及到性能,我仍然认为第一个问题对于编译器读取/计算更少的信息这一事实来说具有非常微小的优势

谈论优化没有任何意义

  • 没有一个明确的目标体系
  • 在确保所有编译器优化都已启用并正常工作之前
  • 在您执行某种基准测试之前
在您的情况下,对于大多数系统,这两个示例之间没有区别。您真正应该关注的是编写可读代码,而不是做相反的事情。考虑把你的程序改写成这样的:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    *bitIndex %= 8;
}
for(i = 0; i < arrayLength; i++)
{
    (*bitIndex)++;
    SETBIT(&result[i / 8], *bitIndex, array[i]);
    *bitIndex %= 8;
}
(i=0;i { (*bitIndex)+; SETBIT(&结果[i/8],*bitIndex,数组[i]); *bitIndex%=8; }
这可能会产生与您已有的完全相同的二进制可执行文件,+-几个CPU周期。

谈论优化没有任何意义

  • 没有一个明确的目标体系
  • 在确保所有编译器优化都已启用并正常工作之前
  • 在您执行某种基准测试之前
在您的情况下,对于大多数系统,这两个示例之间没有区别。您真正应该关注的是编写可读代码,而不是做相反的事情。考虑把你的程序改写成这样的:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    *bitIndex %= 8;
}
for(i = 0; i < arrayLength; i++)
{
    (*bitIndex)++;
    SETBIT(&result[i / 8], *bitIndex, array[i]);
    *bitIndex %= 8;
}
(i=0;i { (*bitIndex)+; SETBIT(&结果[i/8],*bitIndex,数组[i]); *bitIndex%=8; }
这可能会产生与您已有的完全相同的二进制可执行文件,+-几个CPU周期。

您不会说为什么
bitIndex
是指针。但是,假设
bitIndex
是包含给定循环的函数的参数,我会将
*bitIndex
内容从循环中拉出,因此:

  unsigned bi = *bitIndex ;

  for(i = 0 ; i < arrayLength ; i++)
    {
      result[i / 8] = SETBIT(&result[i / 8], ++bi, array[i]) ;
      bi %= 8 ;
    } ;

   *bitIndex = bi ;
unsigned bi=*bitIndex;
对于(i=0;i
[我假设
++bi
是正确的,
SETBIT()
需要1..8,其中
bi
是0..7。]

如其他地方所述,编译器的早餐是
%8
,并将其替换为
&0x7
(用于未签名,但不用于已签名)。对于gcc-O2,上面生成了48字节代码(15条指令)的循环。在循环中摆弄
*bitIndex
是50字节的代码(16条指令),包括一次读取和两次写入
*bitIndex

这有多大的实际区别是任何人的猜测。。。可能是内存读写完全被循环的其余部分所包含


如果
bitIndex
是一个指向局部变量的指针,那么编译器将在循环期间独自将值拉入寄存器——因此它认为值得这么做

您不会说为什么
bitIndex
是指针。但是,假设
bitIndex
是包含给定循环的函数的参数,我会将
*bitIndex
内容从循环中拉出,因此:

  unsigned bi = *bitIndex ;

  for(i = 0 ; i < arrayLength ; i++)
    {
      result[i / 8] = SETBIT(&result[i / 8], ++bi, array[i]) ;
      bi %= 8 ;
    } ;

   *bitIndex = bi ;
unsigned bi=*bitIndex;
对于(i=0;i
[我假设
++bi
是正确的,
SETBIT()
需要1..8,其中
bi
是0..7。]

如其他地方所述,编译器的早餐是
%8
,并将其替换为
&0x7
(用于未签名,但不用于已签名)。对于gcc-O2,上面生成了48字节代码(15条指令)的循环。在循环中摆弄
*bitIndex
是50字节的代码(16条指令),包括一次读取和两次写入
*bitIndex

这有多大的实际区别是任何人的猜测。。。可能是内存读写完全被循环的其余部分所包含


如果
bitIndex
是一个指向局部变量的指针,那么编译器将在循环期间独自将值拉入寄存器——因此它认为值得这么做

量。优化量。对此的任何答案都将取决于编译器的版本及其优化设置。下一个版本可能会使答案无效。您可以使用:i>>3,而不是除以8;它不比i/8慢,但可能更快,具体取决于编译器选项,等等。您也可以尝试
*bitIndex&=7…除非您知道这行代码会导致性能问题,否则您可能应该选择可读性最高的变体。@glezmen,
8
是一个常量,因此编译器应该知道
i/8
i>>3
是等价的(对于正值),所以