编译器不执行别名.您的程序可能会执行别名.
编译器要么允许您执行别名,要么假定您没有执行别名,然后编写如果您执行了别名则不起作用的机器码.
例如,您可以编写如下代码:
void f(int *x, int *y, int *z) {
*y += *x;
*z += *x;
}
该函数只是将*x
与*y
和*z
相加,对吗?所以汇编代码应该是这样的,对吗?(我用伪C编写汇编代码)
eax = argument x
ebx = argument y
ecx = *eax
*ebx += ecx
ebx = argument z
*ebx += ecx
103如果y
和x
指向同一位置,则此汇编代码的工作方式与C代码不同,因为它使用old *x
.要正确运行,它必须是这样的:
eax = argument x
ebx = argument y
ecx = *eax
*ebx += ecx
ebx = argument z
ecx = *eax // extra instruction
*ebx += ecx
这是另一条指令,只有在x==y
的情况下才有用,但编译器必须把它放在那里,以防万一.Aliasing表示*x
和*y
是同一变量的不同名称.如果编译器假设x
和y
不能是同一个指针(即没有别名),那么它可以跳过这条指令,因此指令更少,程序运行得更快.
您可以使用单词restrict
来告诉编译器它们没有别名,如下所示:
void f(int *restrict x, int *restrict y, int *restrict z) {
*y += *x;
*z += *x;
}
-fno-alias
告诉英特尔编译器别名不能在任何地方发生.这可能会产生错误somewhere,因为参数有时会产生别名--尽管它可能在没有别名的小程序上工作得很好.restrict
更仔细地针对您知道不会有别名的特定参数.