在C中使用输入参数而不是局部变量更有效吗?

时间:2016-09-13 16:47:26

标签: c variables optimization parameters

考虑以下两个功能。这两个函数计算字符在具有指定长度的字符串中出现的次数。

pandas

显然,这两个函数做同样的事情。除了第一个函数比第二个函数更易读之外,第二个函数是否更有效,因为它避免了局部变量?我确信这些特定的功能实在太简单,无法衡量真正的差异。我更多地采用一般性或理论性的方式。

用户是否应该避免将输入参数用作临时存储(除了可读性)?我没有询问指针,输入可以通过函数改变。编译器是否以不同的方式解释这两个函数,这可能导致函数1成为首选函数?

我搜索了这些问题,我确实找到了一些相关的问题,但没有一个我能找到的讨论效率。

1 个答案:

答案 0 :(得分:2)

TL; DR

编写您最容易阅读/编写/维护的代码。使用优化进行编译时,函数之间的差异可能会消失。

您可能想要考虑一些可以编写更灵活功能的事情,或者至少:更容易阅读的代码。这个答案将更多地关注编码风格,而不是问题 哪个最好,X或Y ,因为答案几乎总是 这取决于ž

鉴于您允许调用为字符串长度传递0值,您可以编写如下内容:

int get_char_count(const char *str, char c)
{
    int count = 0;
    while(*str++) {
        if (*str == c) {
            ++count;
        }
    }
    return count;
}

对我而言,这看起来像代码量最少,易于阅读,易于维护。 缺点是:

  • 使用此方法,在单个调用中无法完整处理中间带'\0'个字符的字符串(即char[][]
  • 无法在字符串的部分中获取字符数。
  • 无法完整处理包含'\0'字符的字符串

如果要支持这些用例,则必须添加长度参数。但即便如此,我只是将它添加到函数中,而不是调用strlen

int get_char_count(const char *str, char c, unsigned int len)
{
    int count = 0;
    if (!len) {
        while(*str++) {
            if (*str == c) {
                ++count;
            }
        }
        return count; // return early
    }
    //len is given
    while (len--) {
        if (str[len] == c) {
            ++count;
        }
    }
    return count;
}

现在我可以指定要迭代的字符数,而不是返回'\0',我可以使用此函数,例如,计算给定字符的出现次数。字符串数组:

第一种情况(char [][])的工作原理是因为数组如何存储在内存中:数组是一个连续的内存块,所有值都是连续存储的。如果您知道所述块的总大小,则可以使用char[][],就像它是一个大字符串一样。结果是:只需要1个函数调用来计算数组所有元素中的字符。

最后一种情况几乎是一回事,因为示例中的字符串实际上是如何存储字符串数组。

第二个例子(以部分字符串计算)是不言而喻的:您可以指定要检查的字符数,而不是指定完整字符串的长度。
对于缺少终止空字符的字符串,可以使用相同的方法

因为这是一个相当简单的实现功能,所以通常会看到大多数括号被省略:

while (*str++)
    if (*str == c)
        ++count;
//or even
while(len--) count += str[len] == c;

最后一个版本在技术上是有效的,但它并不容易阅读。忽略单行if和简单循环的括号是相当常见的,但是几年前就像the goto fail bug一样导致了错误。

最后一个与风格相关的事情:
当使用指针迭代字符串时,就像我在第一个片段中所做的那样,有些人会告诉你最好的办法是创建一个增量的本地指针:

int get_char_count(const char *str, char c)
{
    int count = 0;
    const char *local = str;
    while(*local++) {
        if (*local == c) {
            ++count;
        }
    }
    return count;
}

这里的明显优势是你没有丢失传入的原始位置/指针。如果你以后在函数中添加了一些内容,你可以随时重新分配,或者根据str分配新的指针。