在下面的代码中
label:
int a;
goto label;
是否创建新变量或使用相同的变量
当我们使用goto
答案 0 :(得分:2)
首先,这不会构建,因为标签后面必须跟一个语句,而声明不是声明:
6.8.1标记语句
语法的
1 labeled-statement: identifier : statement case constant-expression : statement default : statement
其次,这个不应该创建一个新变量。 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
答案 1 :(得分:1)
否它不会再次声明该变量并为其分配任何内存。它将使用相同的变量。
而且你的程序错了,标签不能在任何声明面前,它必须在声明和声明之前不是声明。所以为了纠正它,在标签后加上一个半冒号。
答案 2 :(得分:1)
这个问题也可能是“编译器如何以及何时分配局部变量?”,因为这是问题所在。
假设我们有这样的代码:
{
lots_of_code();
int x;
lots_of_code();
x = 5 + something;
lots_of_code_not_using_x();
return x;
}
此代码位于本地范围内。在这种情况下,它看起来像函数的内部,但相同的规则将适用于if语句的内部,for循环等。遇到此代码时,编译器会问自己一些问题:
x = 5 + something;
之前肯定不会分配x。即使这样也不一定分配,编译器也可以重新排序指令,首先选择执行lots_of_code_not_using_x();
,如果它更有效并且不改变代码的含义。在这种情况下,当代码到达return语句时分配x。x保证标准从进入范围一直有效,直到范围结束。 9899:2011 6.2.4
“5声明标识符没有链接且没有链接的对象 存储类说明符static具有自动存储持续时间,如 做一些复合文字......“/ - /
“6对于没有可变长度数组类型的对象, 其生命周期从进入与其关联的块延伸,直到该块的执行以任何方式结束。 (进入 封闭的块或调用函数暂停但不结束, 执行当前块。)如果以递归方式输入块, 每次都会创建一个新的对象实例。初始值 对象是不确定的。如果指定了初始化 对象,每次声明或复合时执行 在块的执行中达到了字面值;否则,价值 每次达到声明时都变得不确定。“
所以回答这个问题:不,你的goto spaghetti不会影响变量的分配方式。如果有任何使用该变量的代码,例如int a = 0;
那么该代码可能会一遍又一遍地执行,这取决于编译器如何智能地优化掉整个goto混乱。