7

在一个教程中它说

如果使用 goto 语句跳转到块的中间,则不会初始化该块中的自动变量。

然后在下面的代码中,如果我可以被访问/声明,那么为什么它没有被初始化?

int main()
{
   goto here;
   {
     int i=10;
     here:
      printf("%d\n",i);
   }
   return 0;
}

ps:输出是一些垃圾值。

4

6 回答 6

12

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.

于 2012-07-12T08:18:58.437 回答
3

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.

于 2012-07-12T08:20:13.023 回答
2

考虑另一种明显的情况:

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'跳过

于 2012-07-12T08:42:57.343 回答
0

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.

于 2012-07-12T08:20:59.093 回答
0

因为语言标准是这样说的:

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。

于 2012-07-12T08:43:40.730 回答
-1

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.

于 2012-07-12T08:20:21.180 回答