请看这段微小的C代码或C++代码,它在godbolt上......
void b( char const *c);
void a(void)
{
char const z[] = {0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf, 0xa};
b(z);
}
void c(void)
{
static char const z[] = {0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf, 0xa};
b(z);
}
早期版本的gcc将a()和c()编译为两条指令:加载z的地址并跳转到b。我尝试过的所有现代编译器都会将a()“悲观化”为“创建堆栈帧,将z复制到堆栈上,调用b,拆除堆栈帧,但将c()保留为两条指令的简单版本。”
实际上没有任何变化,在这种情况下现代编译器在实践中变得更慢了.....
有人知道为什么吗?
c()
的b(z)
传递了一个指向数组的指针,该指针在b()
完成后仍然有效。但是a()
的b(z)
不是这样。有趣的是,将restrict
添加到void b(char const * restrict c);
中是否会改变情况? - chux - Reinstate Monicastatic char const z[]
,表示z
是静态变量。静态变量必须位于数据段中。因此编译器会使用两条指令。对于char const z[]
,z 是常量变量,我认为编译器可以将其放在数据段或堆栈中。我认为这只是编译器的选择,但并不确定。如果使用char z[]
,那么编译器将把z放在堆栈中,然后函数a将有更多的指令。 - randomeval