通过索引访问数组的项目

问题描述 投票:0回答:4

假设我在循环内使用数组的一项,例如

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];
}
c optimization
4个回答
1
投票

如有疑问,您可以尝试一下。 例如,将你的两段代码放入函数中:

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 告诉编译器生成汇编代码并停止。

然后看汇编代码。

即使您不太了解汇编程序,您也应该能够了解两个函数的相对大小。 对于您的函数,它们会编译为相同的代码。


1
投票

很大程度上取决于您的编译器和编译器设置。

不过,一般来说我不会担心。


0
投票

几乎任何级别的优化,编译器都可能为两个片段生成相同的代码。 事实上,如果不进行优化,没有显式局部变量的版本可能会做得更好,因为它不需要显式存储

g_ins[i]
的值;它可能只是放入一个寄存器并使用它两次。

但是,它确实取决于您使用的编译器和优化设置。 而且这里的任何差异不太可能是快速程序和慢速程序之间的差异。


0
投票

大多数编译器会在正常设置中避免此类事情。您的变量是在循环之外声明的,编译器不确定循环后是否有任何进一步使用 INS *in 。因此,跳过此阶段除了节省一些时间外不会做太多优化指令,但可能导致后期输出损坏。

© www.soinside.com 2019 - 2024. All rights reserved.