提高这段代码可读性的建议

Suggestions for improving the readability of this code

我不确定是否应该在这里或其他 StackExchange 网站上提问,但我会继续...如果这里不合适请迁移)

我正在审查代码。要求是调用参数范围为 0 到 n 的函数 n 次。但是如果n大于7,只调用函数7次。

我的同事是这样实现的:

void ExecuteFunctions(U8 count)
{
    if(count > 0) oprA(0);
    if(count > 1) oprA(1);
    if(count > 2) oprA(2);
    if(count > 3) oprA(3);
    if(count > 4) oprA(4);
    if(count > 5) oprA(5);
    if(count > 6) oprA(6);
    if(count > 7) oprA(7);
}

我修改为:

void ExecuteFunctions(U8 count)
{
    for(U8 loopcnt = 0; loopcnt < count; loopcnt++)
    {
        oprA(loopcnt);

        if(loopcnt == 7)
        {
            // We don't want to execute this function more number of times if it is already executed 7 times
            break;
        }
    }
}

但我仍然觉得可能有更好的方法,需要您的意见。 (如果这里离题,也请迁移)

MIN 是一个有用且经常定义的宏

#define MIN(a,b)     (((a) > (b)) ? (b) : (a))
#define MAX_STEP 7

void ExecuteFunctions(U8 count)
{
    int loopcnt = 0;
    count = MIN(count, MAX_STEP);

    while(loopcnt++ < count) {
        oprA(loopcnt);   
    }
}

让编译器优化吧。我觉得以下内容更具可读性:

void ExecuteFunctions(U8 count)
{
    for(U8 loopcnt = 0; loopcnt < count && loopcnt < 8; loopcnt++)
    {
        oprA(loopcnt);
    }
}

当然,您需要 运行 分析器来实际评估程序的性能。

我会写成

void ExecuteFunctions(unsigned count) {
    // Could use min() too if available.
    unsigned iters = count < 7 ? count : 7;

    for (unsigned i = 0; i < iters; ++i)
        oprA(i);
}

使用 GCC 4.9 和 -O3 在 X86_64 上为此函数生成的代码大小约为 36 字节。原始版本的大小是141字节(GCC似乎不太聪明)。

请注意,传递纯 ints、unsigned ints、size_ts 等通常比仅因为您知道值会很小而缩小参数范围更好。编译器通常可以更轻松地为具有适合体系结构的自然大小的变量生成良好的代码。当您需要存储大量数据时例外。

更新:

以下版本(根据 Austin 的回答稍作修改——抱歉盗用了它 :))顺便提供了 32 个字节。我觉得我更喜欢它。

void ExecuteFunctions(unsigned count) {
    for (unsigned i = 0; i < count && i < 8; ++i)
        oprA(i);
}
void ExecuteFunctions(U8 count)
{
    for(U8 loopcnt = 0; loopcnt < (count & 7); loopcnt++)
    {
        oprA(loopcnt);
    }
}

如果你真的喜欢switch语句,试试这个,看看它是否能通过代码审查:

void ExecuteFunctions(U8 count) {
    int i = 0;
    switch (count) {
      default: oprA(i++);
      case 6:  oprA(i++);
      case 5:  oprA(i++);
      case 4:  oprA(i++);
      case 3:  oprA(i++);
      case 2:  oprA(i++);
      case 1:  oprA(i++);
      case 0:  oprA(i);
    }
}