在一个教程中它说
如果使用 goto 语句跳转到块的中间,则不会初始化该块中的自动变量。
然后在下面的代码中,如果我可以被访问/声明,那么为什么它没有被初始化?
int main()
{
goto here;
{
int i=10;
here:
printf("%d\n",i);
}
return 0;
}
ps:输出是一些垃圾值。
在一个教程中它说
如果使用 goto 语句跳转到块的中间,则不会初始化该块中的自动变量。
然后在下面的代码中,如果我可以被访问/声明,那么为什么它没有被初始化?
int main()
{
goto here;
{
int i=10;
here:
printf("%d\n",i);
}
return 0;
}
ps:输出是一些垃圾值。
There's no logic behind your question "if i
can be accessed, why...". Being able to "access i
" isn't an argument for or against anything. It just means that the printf
statement is in the same scope as i
. However, since you jumped over the initializer, the variable is uninitialized (just as your tutorial says).
Reading an uninitialized variable is undefined behaviour, so your program is ill-formed.
The memory for the variable i
has already been set aside at compile time, since the variable is known to exist inside the inner block. The memory doesn't get allocated dynamically, as you may be imagining. It's already there, but it never got set to anything determinate because of the goto
.
Rule of thumb: Don't jump across initializers.
Variables are visible in the scope in which they are declared (between the {}
in this case), irrespective of the order of execution of the statements within that scope. The goto
bypasses the initialization of i
, meaning it has an undefined value when the printf()
is invoked.
考虑另一种明显的情况:
int main()
{
int i; //i is declared, but not initialized
goto here;
{
i=10;//i is initialized
here: //you've skipped the initialization
printf("%d\n",i);//and got garbage
}
return 0;
}
在你的情况下:
int main()
{
goto here;
{
//printf("%d\n",i); // i does not exist here yet
int i; //from here until the end of the scope variable i exists
i=10; // i exists here and smth is written into it
here: // i exists here
printf("%d\n",i); // i exists here and it's value is accessed
}
return 0;
}
所以,int i = 5;
这真的是两件事。一个是声明,不能被任何东西跳过,包括goto
(就像打开一个新的范围也不受影响。你已经跳到了范围的中间,但范围已经在那里了)。其次是操作分配,因为它是正常操作(程序流程)它可以被goto
或'break'或'continue'或'return'跳过
The C compiler will parse the source file and it "records" any variable initializations.
When it reaches
printf("%d\n", i)
it will know that the variable i already exists and he should be able to use it, since it is in scope.
At execution space is reserved for the i variable on the stack right after the call of the main function, and before any of the code in main() is executed.
因为语言标准是这样说的:
6.7.8 初始化
语义
如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。
J.2 未定义的行为
在以下情况下,行为未定义:
具有自动存储持续时间的对象的值在不确定时使用。
6.8.4.2 switch 语句
示例 在仿真程序片段中
switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
/* falls through into default code */
default:
printf("%d\n", i);
}
标识符为 i 的对象存在自动存储持续时间(在块内)但从未初始化,因此如果控制表达式具有非零值,则对 printf 函数的调用将访问一个不确定的值。同样,无法调用函数 f。
C lets you access anything within your address space, whether it's actually initialized or not. Sometimes working like that crashes or shows garbage, sometimes it happens to print something useful, but it's all undefined behavior. Handy trick, but a great way to break your program, so don't think that just getting a result means your trick works.