假设我在循环内使用数组的一项,例如
INS *in;
for (int i = 0; i < LEN; i++) {
in = g_ins[i];
if (strcmp(in->mne, str) == 0)
return in;
}
如果我使用索引引用每个引用,编译器会将其优化为类似上面的内容,或者它真的一次又一次地访问每个索引?
for (int i = 0; i < LEN; i++) {
if (strcmp(g_ins[i]->mne, str) == 0)
return g_ins[i];
}
如有疑问,您可以尝试一下。 例如,将你的两段代码放入函数中:
INS * f1 (INS *g_ins, const char * str)
{
for (int i = 0; i < LEN; i++) {
INS *in = &g_ins[i];
if (strcmp(in->mne, str) == 0)
return in;
}
return NULL;
}
INS * f2 (INS *g_ins, const char * str)
{
for (int i = 0; i < LEN; i++) {
if (strcmp(g_ins[i].mne, str) == 0)
return &g_ins[i];
}
return NULL;
}
然后使用 -O2 和 -S 编译它们(例如
gcc -std=c99 -O2 -S -Wall code.c -o code.s
)。 -O2 设置优化级别,-S 告诉编译器生成汇编代码并停止。
然后看汇编代码。
即使您不太了解汇编程序,您也应该能够了解两个函数的相对大小。 对于您的函数,它们会编译为相同的代码。
很大程度上取决于您的编译器和编译器设置。
不过,一般来说我不会担心。
几乎任何级别的优化,编译器都可能为两个片段生成相同的代码。 事实上,如果不进行优化,没有显式局部变量的版本可能会做得更好,因为它不需要显式存储
g_ins[i]
的值;它可能只是放入一个寄存器并使用它两次。
但是,它确实取决于您使用的编译器和优化设置。 而且这里的任何差异不太可能是快速程序和慢速程序之间的差异。
大多数编译器会在正常设置中避免此类事情。您的变量是在循环之外声明的,编译器不确定循环后是否有任何进一步使用 INS *in 。因此,跳过此阶段除了节省一些时间外不会做太多优化指令,但可能导致后期输出损坏。