在for循环中会调用strlen()多少次?

bet*_*een 12 c loops

下面的strlen()函数是否只被调用一次(存储的值用于进一步的比较); 或者每次进行比较时都会调用它?

for (i = 0; i < strlen(word); i++)
{ /* do stuff */ }
Run Code Online (Sandbox Code Playgroud)

Chr*_*ung 28

这是依赖于实现的.通常,它每次都被调用,但是,如果编译器可以看到word永远不会改变,并且这strlen是一个纯函数(没有副作用),它可以解除调用.

请参阅:http://underhanded.xcott.com/?page_id = 15,了解有关此漏洞的一个众所周知的示例.:-)

  • @Chris:这个函数是一元的并不一定有助于别名,也没有只将`word`传递给带有`char const*`的函数.如果`word`是非限制的,则可能存在一个全局`char*`,被调用者修改,而恰好是`word`的别名.如果被调用者位于不同的翻译单元中,并且不是以某种方式标记为纯粹的,那么编译器几乎肯定无法排除这种情况,尽管整个程序优化可能会得到另一个镜头.基本上,如果循环体没有完全内联,那么不要屏住呼吸. (3认同)
  • 说实话,每次我尝试阅读C99标准中限制的定义时,我都会头疼,并且必须观看漫画一段时间以冷却我的大脑;-).但是,是的,我非常确定在其范围内"通过"任何其他引用时,不得修改限制指针,无论该引用是否是另一个参数.因此,我认为即使在函数中(例如)通过函数指针回调用户定义的代码时,restrict也允许优化,而无需任何静态分析. (2认同)

Kal*_*see 8

它将针对循环的每次迭代进行评估(编辑:如果需要).

就像Tatu说的那样,如果word不会改变长度,你可以strlen在for循环之前进行调用.但正如克里斯所说,编译器可能足以实现word无法改变,并消除重复调用本身.

但是如果word在循环期间可以改变长度,那么当然你需要将strlen调用保持在循环条件下.

  • @Noldorin:由于别名,它需要的不仅仅是"中途正常的编译器".如果循环通过指针修改函数中的*any*内存,或调用*any*代码执行此操作或可能执行此操作,那么编译器可能无法假设有问题的指针未指向相同的内存. word`.如果`word`在C99中用关键字`restrict`标记,那么它可以做出这个假设,并且在一些罕见的情况下它可能能够证明没有别名.但是,如果没有看到循环的主体,你不能说这是一个简单的优化. (2认同)

Chr*_*isW 6

我有时会将其编码为......

for (int i = 0, n = strlen(word); i < n; ++i) { /* do stuff */ }
Run Code Online (Sandbox Code Playgroud)

...所以strlen只被调用一次(以提高性能).