(抱歉英文不好。)
问题1。
void foo(void)
{
goto inside;
for (;;) {
int stack_var = 42;
inside:
...
}
}
将分配给堆栈的位置 stack_var
当我转到 inside
标签?即我能正确使用吗? stack_var
内变量 ...
?
问题2。
void foo(void)
{
for (;;) {
int stack_var = 42;
...
goto outside;
}
outside:
...
}
将是一个堆栈的地方 stack_var
当我转到时,我解除了分配 outside
标签?例如。这样做是否正确 return
中 ...
?
换句话说,是 goto
智能正确使用堆栈变量(当我走过块时自动(de)分配),或者它只是一个愚蠢的跳跃?
问题1:
我可以正确使用...内的stack_var变量吗?
...中的代码可以写入 stack_var
。但是,这个变量是未初始化的,因为执行流程跳过了初始化,因此代码不应该在没有先写入的情况下从中读取。
从C99标准来看,6.8:3
每次按执行顺序达到声明时,将评估具有自动存储持续时间[...]的对象的初始化程序,并将值存储在对象中(包括在没有初始化程序的对象中存储不确定值)
我的编译器将下面的函数编译成一个程序集,有时会返回未初始化的内容 x
:
int f(int c){
if (c) goto L;
int x = 42;
L:
return x;
}
cmpl $0, %eax
jne LBB1_2
movl $42, -16(%rbp)
LBB1_2:
movl -16(%rbp), %eax
...
popq %rbp
ret
问题2:
当我转到外部标签时,将在堆栈中放置一个堆栈的地方吗?
是的,你可以期待保留的内存 stack_var
一旦变量超出范围就被收回。
有两个不同的问题:
并且局部变量只能保存在寄存器中(调用帧中没有任何插槽),并且该寄存器显然可以用于各种目的。
你可能会受伤 未定义的行为 为你的第一个案例。之后 goto inside
该 stack_var
没有初始化。
我建议你编译 gcc -Wall
并改善代码直到没有给出警告。