编译器不执行别名。您的程序可能会执行别名操作。
编译器要么允许您执行别名,要么假设您没有执行别名,然后编写在您执行别名时不起作用的机器代码。
例如,您编写这样的代码:
void f(int *x, int *y, int *z) {
*y += *x;
*z += *x;
}
该函数只是添加*x
to *y
and *z
, 正确的?那么汇编代码应该是这样的吧? (我用伪C语言编写了汇编代码)
eax = argument x
ebx = argument y
ecx = *eax
*ebx += ecx
ebx = argument z
*ebx += ecx
Wrong. If y
and 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
and *y
是同一个变量的不同名称。如果编译器假设x
and y
不能是相同的指针(即没有别名),那么它可以跳过该指令,因此指令更少,程序运行得更快。
您可以使用单词告诉编译器他们不使用别名restrict
, 像这样:
void f(int *restrict x, int *restrict y, int *restrict z) {
*y += *x;
*z += *x;
}
-fno-alias
告诉英特尔编译器别名不能在任何地方发生。这可能会产生错误某处因为参数有时会产生别名 - 尽管它可能在它们都没有的小程序上工作得很好。restrict
更仔细地针对您知道不会别名的特定参数。