如果在循环条件下使用,是否会多次计算strlen?

dai*_*isy 108 c c++ optimization gcc strlen

我不确定以下代码是否会导致冗余计算,还是特定于编译器?

for (int i = 0; i < strlen(ss); ++i)
{
    // blabla
}
Run Code Online (Sandbox Code Playgroud)

strlen()每次i增加时会计算出来吗?

Mik*_*our 135

是的,strlen()将在每次迭代时进行评估.在理想的情况下,优化者可能会推断出价值不会改变,但我个人不会依赖于此.

我会做点什么的

for (int i = 0, n = strlen(ss); i < n; ++i)
Run Code Online (Sandbox Code Playgroud)

或者可能

for (int i = 0; ss[i]; ++i)
Run Code Online (Sandbox Code Playgroud)

只要字符串在迭代期间不会改变长度.如果可能,那么你需要strlen()每次调用,或者通过更复杂的逻辑来处理它.

  • @alk:如果字符串可能缩短,那么这两个都是错误的. (25认同)
  • 如果你知道你没有操纵字符串,那么第二个就更好了,因为那基本上是`strlen`执行的循环. (14认同)
  • 第二个版本是理想和最惯用的形式.它允许您仅将字符串传递一次而不是两次,这对于长字符串将具有更好的性能(尤其是缓存一致性). (6认同)
  • @mcl:当然,如果...... ;-) (3认同)
  • @alk:如果你要更改字符串,for循环可能不是迭代每个字符的最佳方法.我认为while循环更直接,更容易管理索引计数器. (3认同)
  • *理想情况*包括在linux下编译GCC,其中`strlen`被标记为`__attribute __((pure))`允许编译器忽略多个调用.[GCC属性](http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) (2认同)

cod*_*TER 14

是的,每次使用循环.然后它会每次计算字符串的长度.所以像这样使用它:

char str[30];
for ( int i = 0; str[i] != '\0'; i++)
{
//Something;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码str[i]中,i每次循环开始循环时,只验证字符串中的一个特定字符,因此它将占用更少的内存并且更有效.

有关更多信息,请参阅此链接.

在每次循环运行时,下面的代码strlen将计算整个字符串的长度,效率较低,需要更多时间并占用更多内存.

char str[];
for ( int i = 0; i < strlen(str); i++)
{
//Something;
}
Run Code Online (Sandbox Code Playgroud)

  • 我同意"[它]效率更高",但使用更少的内存?我能想到的唯一内存使用差异是在`strlen`调用期间的调用堆栈中,如果你运行得那么紧,你可能应该考虑省略其他一些函数调用...... (3认同)

Mis*_*sch 9

一个好的编译器可能不会每次都计算它,但我认为你不能确定,每个编译器都会这样做.

除此之外,编译器必须知道,这strlen(ss)不会改变.只有ssfor循环中没有改变时才会出现这种情况.

例如,如果ssfor循环中使用只读函数但未将ss-parameter 声明为const,则编译器甚至不知道ss循环中没有更改,并且必须strlen(ss)在每次迭代中计算.

  • 我认为编译器不太可能知道"ss"不会改变.可能存在指向"ss"内存的杂散指针,编译器不知道这可能会改变"ss" (4认同)
  • 关于你的最后一段:如果你在for循环中调用`ss`上的只读函数,那么即使它的参数被声明为`const char*`,编译器*仍然*需要重新计算长度,除非(a) )它知道`ss`指向一个const对象,而不是只是指向const的指针,或者(b)它可以内联函数或以其他方式看到它是只读的.取一个`const char*`参数是*not*一个不会修改指向的数据的承诺,因为只要被修改的对象不是const而不是字符串,它就可以强制转换为`char*`并修改文字. (4认同)
  • +1:不仅必须在`for`循环中改变`s`; 它不能被循环中调用的任何函数访问和更改(因为它作为参数传递,或者因为它是全局变量或文件范围变量).限定资格也可能是一个因素. (3认同)
  • @MerickOWA:的确,这是C99中"限制"的内容之一. (2认同)