如何解决循环计数器和指针
| 我正在为图形编写一个小型的专用C99库,并且经常收到以下形式的循环:for(int i = 0; i < graph->nvertices; ++i) {
// ...
}
我想知道这是否是一个好习惯,特别是在小循环的情况下。起初,我认为编译器足够聪明,只需要查看\'graph-> nvertices \一次,而不是每次迭代都查看它,但是由于graph-> nvertices可以在循环内更改,因此这似乎是不可能的。 Is更聪明,更快速地编写:
const int N = graph->nvertices;
for(int i = 0; i < N; ++i) {
// ...
}
似乎更快,因为它不需要多次查看指针,但是确实需要创建一个新变量。
注意:我猜这是一种情况,如果有人有很好的参考资料,我很愿意阅读一些汇编代码,以查看编译器的实际运行情况。
解决方法
尝试使用更高的优化设置,某些编译器应该可以为您优化这些设置。您还可以向后迭代,仅使用表达式初始化计数器:
for (int i = graph->nvertices; i >= 0; --i)
..
但是,您将对缓存性能造成严重破坏。我认为您建议的方法是最简单的方法,它可以使编译器和下一个阅读代码的人都清楚知道。
, 我倾向于自己进行这些优化。有时,编译器可以推断出nvertices
不会在整个循环中改变,但是如果您调用了可能改变其值的其他函数,该怎么办?编译器无法推断出它,也可能无法优化代码。
另外,最好的方法始终是对代码进行性能分析,以查看两种方法之间的比较。
, 我通常使用这个。
const int N = graph->nvertices;
int i = 0;
for(; i < N; ++i) {
// ...
}
, 答案可能取决于您的编译器,但是大多数编译器都会为您提供一个程序集列表,您可以研究该列表。只要确保您列出了发行版本即可。
但是,如果我真的很关心性能的每一个方面,我可能会按照您的建议创建单独的count变量。
最后,我怀疑这会带来明显的差异。
, 您要求一种查看汇编代码的方法。为此,您可以使用objdump
程序,如下所示:
objdump -d executable
要过滤出主要功能,请使用:
objdump -d executable | sed -n \'/<main>/,/^$/p\'
, 仅通过查看编译器的输出,这似乎很容易测试。整个程序优化通常会捕获这些低级优化。
另一方面,即使速度稍有提高,我通常也不会进行这些类型的优化,因为我发现第一种形式更易于阅读和维护。
, 我会去本地化变量的范围。然后,优化器将自行解决所有问题:
for(size_t i = 0,n = graph->nvertices; i < n; ++i) {
// ...
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。