编译器可能会优化掉结构的副本,而是直接从数组访问成员以提供使用副本的 C 代码中所需的值,或者可能只复制您使用的单个成员。一个好的编译器会做到这一点。
通过指针存储值可能会干扰这种优化。例如,假设您的例程还有一个指向 int, 的指针p。当编译器处理你的代码INS in = *ins[i]时,它可能会“思考”这样的事情:“复制ins[i]是昂贵的。取而代之的是,我会记住那in是一个副本,稍后我会为它获取成员,当他们使用时。” 但是,如果您的代码包含*p = 3,这可能会改变ins[i],除非编译器能够推断出p不指向ins[i]. restrict(有一种方法可以帮助编译器使用关键字进行推断。)
总结:表面上看起来很昂贵的操作可能由一个好的编译器有效地实现。看起来便宜的操作可能很昂贵(写入会*p破坏大的优化)。通常,您应该编写清楚地表达您的算法的代码并让编译器进行优化。
扩展编译器如何优化它。假设你写:
for (int i = 0; i < N; i++) {
INS in = *ins[i];
...
}
其中“...”中的代码访问 in.str 和 in.len,但不访问您添加到 INS 结构的其他 237 个成员中的任何一个。然后编译器可以自由地将这段代码转换为:
for (int i = 0; i < N; i++) {
char *str = *ins[i].str;
int len = *ins[i].len;
...
}
也就是说,即使您编写了一个语句,表面上复制了所有 INS 结构,但编译器只需要复制实际需要的部分。(实际上,甚至不需要复制那些部分。只需要生成一个程序,获得与直接遵循源代码相同的结果即可。)