p1->p2->p3
在可能的情况下,编译器将通过将重复使用的基本位置保存在寄存器中(例如在您的示例中)来为您消除开销。
但是,有时编译器无法确定哪些指针可能会为您的函数中使用的其他指针起别名——这意味着它必须回退到一个非常保守的位置,并经常从指针重新加载值。
这就是 C99 的restrict
关键字可以提供帮助的地方。当某些指针永远不会被函数范围内的其他指针所别名时,它可以让您通知编译器,从而可以改进优化。
例如,使用这个函数:
struct xyz {
int val1;
int val2;
int val3;
};
struct abc {
struct xyz *p2;
};
int foo(struct abc *p1)
{
int sum;
sum = p1->p2->val1 + p1->p2->val2 + p1->p2->val3;
return sum;
}
在具有优化级别的 gcc 4.3.2 下-O1
,它编译为以下 x86 代码:
foo:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl (%eax), %edx
movl 4(%edx), %eax
addl (%edx), %eax
addl 8(%edx), %eax
popl %ebp
ret
正如你所看到的,它只引用p1
一次——它将值保存p1->p2
在%edx
寄存器中并使用它三次从该结构中获取三个值。