C通过将语句嵌入循环头本身来优化循环
只是想知道 for 循环的这些变体是否更有效和实用。通过使用 c for 循环语法,我可以将循环体中的语句嵌入到循环头中,如下所示:
示例 1:
#include <stdio.h>
int main(int argc, char ** argv)
{
// Simple program that prints out the command line arguments passed in
if (argc > 1)
{
for(int i = 1; puts(argv[i++]), i < argc;);
// This does the same as this:
// for(int i = 1; i < argc; i++)
// {
// puts(argv[i]);
// }
}
return 0;
}
我理解逗号如何在 for 循环中工作,它按顺序遍历每个语句,评估它们然后忽略除最后一个之外的所有内容,这就是为什么它能够使用“i < argc”条件进行迭代。最后一段不需要像我在循环头的中间段(在 puts(argv[i++]) 位)那样递增 i 变量。这是更有效还是只是将其分离到循环体中而不是将其全部合并为一行更干净?
示例 2:
int stringLength(const char * string)
{
// Function that counts characters up until null terminator character and returns the total
int counter = 0;
for(counter; string[counter] != ' '; counter++);
return counter;
// Same as:
//int counter = 0;
// for(int i = 0; string[i] != ' '; i++)
//{
// counter++;
//}
//return counter;
}
这个似乎比带有循环体的版本更有效,因为没有初始化 for 循环的局部变量。在没有物体的情况下进行这些类型的循环是传统的吗?
回答
第 1 步:正确性
确保代码正确。
考虑下面的 OP 代码。它是否尝试打印argv[argc]哪个不好?
if (argc > 1) {
for(int i = 1; puts(argv[i++]), i < argc;);
我一开始以为是的。另一个用户也是如此。不过还好。
……这正是代码薄弱的原因。
代码不仅应该是正确的,更好的代码看起来也是正确的。使用反模式由OP的建议是很少1的好事。
第 2 步:由于代码变体具有相同的大 O,因此可以理解地关注。
雕刻您的代码 - 删除不需要的内容。
for (int i = 1; i < argc; i++) {
puts(argv[i]);
}
OP 正在做的是一个微不足道的优化问题。
过早优化真的是万恶之源吗?
在没有物体的情况下进行这些类型的循环是传统的吗?
并不真地。
编码风格的关键是遵循团队的风格指南。伟大的软件通常是团队的努力。如果您的团队喜欢最小化身体,请继续。我见过相反的更常见、明确的{ some_code }机构。
注意:int stringLength(const char * string)对于长度超过INT_MAX. 最好size_t用作返回类型——因此是第 1 步步履蹒跚的例子。
1除本规则外,所有编码风格规则都有例外。
- 模糊优化不是优化......(这是一个应用于代码的愚蠢的宠物技巧)转储到汇编和比较。除非使用反模式有显着且有意义的节省,否则不要这样做。