gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 08:11:02 25 4
gpt4 key购买 nike

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

    int str_get_num_occurrences1(char * str, char c, unsigned int len){
if (!len)
len = strlen(str);

int res = 0;
int n = len;

for ( ; n--; )
if (str[n] == c)
res++;

return res;
}

int str_get_num_occurrences2(char * str, char c, unsigned int len){
int res = 0;

if (!len)
len = strlen(str);

for ( ; len--; )
if (str[len] == c)
res++;

return res;
}

显然,这两个函数做同样的事情。除了第一个函数比第二个函数更具可读性这一事实之外,第二个函数是否更有效,因为它避免了局部变量?我敢肯定,这些特定的功能真的太简单了,无法衡量真正的差异。我是以更笼统或理论上的方式提问。

用户应避免将输入参数用作临时存储(除了可读性)的原因有哪些?我不是在问指针,函数可以在其中更改输入。编译器是否以不同方式解释这两个函数,这可能会导致函数一成为首选?

我搜索了这些问题,确实找到了一些相关问题,但我找不到任何讨论效率的问题。

最佳答案

长话短说

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

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


假设您允许调用为字符串长度传递一个 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 [][]) 之所以可行,是因为数组在内存中的存储方式:数组是连续的内存块,所有值都连续存储。如果您知道所述 block 的总大小,则可以将 char[][] 当作一个大字符串来使用。结果是:只需要调用 1 次函数来计算数组所有元素中的一个字符。

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

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


因为这是一个实现起来相当简单的函数,所以通常会看到大部分括号被省略:

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< 分配一个新指针.

关于c - 在 C 中使用输入参数而不是局部变量是否更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39475171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com