1

在下面的一段代码中

label:
int a;
goto label;

它是创建新变量还是使用相同的变量
当我们使用 goto 一次又一次调用函数时会发生什么

4

3 回答 3

2

首先,这不会建立,因为标签必须后跟语句,而声明不是语句:

6.8.1 标记语句

句法

1 标记语句:
        标识符  语句
        case 常量表达式  语句
        默认值  语句

其次,这不应该创建一个新变量。 goto不会引入新范围,因此不会为a每次迭代创建新实例。甚至在您引入新范围的情况下例如

for (;;) {int a; ... }

的空间a(通常)只分配一次;即使从逻辑上讲,您正在处理a每个循环迭代的新实例,但在物理上,您(通常)正在回收相同的内存位置。任何在物理上创建新空间a 而不回收先前空间的编译器都将严重破坏 IMO。

只是为了咯咯笑,我写了以下内容:

#include <stdio.h>

#ifdef __STDC_VERSION__
  #if __STDC_VERSION__ >= 199901L
    #define C99
  #endif
#endif

int main(void)
{
label:
  #ifdef C99
    ;
  #endif
  int a;
  printf("&a = %p\n", (void *) &a); 
  goto label;

  return 0; 
}

用 构建它gcc -std=c99 -pedantic -Wall -Werror,我得到以下输出:

&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
于 2012-06-07T11:53:12.973 回答
1

这个问题也可以是“编译器如何以及何时分配局部变量?”,因为这就是这里的问题。

假设我们有这样的代码:

{
  lots_of_code();

  int x;

  lots_of_code();

  x = 5 + something;

  lots_of_code_not_using_x();

  return x;
}

此代码在本地范围内。在这种情况下,它看起来像函数的内部,但相同的规则将适用于 if 语句、for 循环等的内部。遇到此代码时,编译器会问自己一些问题:

  • 我是否需要分配 x 或者我可以优化它吗?不,在这种情况下 x 不能在不改变代码含义的情况下被优化掉。
  • 分配 x 的最佳位置在哪里?这完全是特定于 CPU 的:x 可以分配在堆栈或 CPU 寄存器等中。
  • 我什么时候分配 x?对此的回答始终是:“第一次使用时”。在这种情况下,在执行该行之前肯定不会分配 x x = 5 + something;。即使这样也不一定分配,编译器也可以重新排序指令,选择首先执行lots_of_code_not_using_x();,如果这样更有效并且不会改变代码的含义。在这种情况下,当代码到达 return 语句时分配 x。

x 由标准保证从进入范围开始一直有效,直到范围结束。9899:2011 6.2.4

“5 其标识符被声明为没有链接且没有存储类说明符 static 的对象具有自动存储持续时间,某些复合文字也是如此......” /--/

“6 对于这样一个没有可变长度数组类型的对象, 它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。(进入封闭的块或调用函数暂停,但不结束,执行当前块。)如果递归进入块,每次都会创建一个新的对象实例。对象的初始值是不确定的。如果为对象指定了初始化,它是在块的执行中每次到达声明或复合文字时执行;否则,每次到达声明时值变得不确定。"

所以回答这个问题:不,你的 goto spaghetti 丝毫不会影响变量的分配方式。例如,如果有任何代码使用该变量,int a = 0;那么该代码可能会一遍又一遍地执行,这取决于编译器优化整个 goto 混乱的智能程度。

于 2012-06-07T11:42:01.887 回答
1

否 它不会再次声明该变量并为其分配任何内存。它将使用相同的变量。

而且你的程序是错误的,标签不能在任何声明之前,它必须在语句之前,并且声明不是语句。因此,要更正它,请在标签后加一个分号。

于 2012-06-07T10:56:04.430 回答