变量作用域行为c语言
Variable scope behavior c language
代码片段:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
变量i
每次重新开始循环时都存储在堆栈中?
运行这段代码的内存结构是什么?
这个变量的行为是什么?
这样做是坏习惯还是好习惯?
谢谢。
你永远达不到i == 500.
因为它在while(1){}.
的范围内所以每次循环都会被重置
以下将起作用。
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
在此代码中,变量 i 将始终为 0 或 1;中断永远不会执行。
变量 i 在 while 循环中声明并且是局部的。
在C语言中,一对大括号可以创建一个新的作用域
隐藏在外部声明的同名变量
范围。
此代码:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
应该改成这样:
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
当 C 中的函数 运行 时,它会为所有需要的局部变量分配 space。如果变量在函数顶部彼此相邻分配,则很容易看出它是如何工作的:
void foo(){
int x;
int y;
y = 1;
x = y + 2;
return x + y;
}
如果变量是在函数的内部块内声明的,编译器所做的是 "lift" 将那些变量声明到函数的顶部。如果存在名称冲突的变量,编译器会为您重命名,以便它们引用正确的变量。
// This is what you write
void original(){
int x = 0;
while(1){
int x = 1;
}
}
// This is what the compiler "sees"
void lifted(){
int x1;
int x2;
x1 = 0;
while(1){
x2 = 0;
}
}
在您的例子中,您的代码表现如下:
void function(void)
{
int i;
while(1)
{
i = 0;
i += 1;
if(i == 500) break;
}
}
在这个版本中,很明显 i 一直被重置为 0,这就是循环将永远 运行 的原因。
至于在内部范围内声明变量是否是一个好习惯,它与内存使用无关,而与变量名的范围有关。一般来说,如果可能的话,将变量限制在内部范围内是一件好事(出于与局部变量优于全局变量的相同原因)。也就是说,您始终必须在循环之前而不是在循环内部初始化变量。在这种情况下,它是关于消除错误而不是成为最佳实践。
从逻辑上讲,循环的每次迭代都会创建一个 i
变量的新实例,该实例仅存在于循环体内。正如所写,这段代码永远不会终止,因为 while
循环的每次迭代都会创建一个 i
的新实例并将其初始化为 0
.
尝试在循环体外部引用 i
会导致未定义的行为; IOW,代码像
int *p;
while ( 1 )
{
int i = 0;
p = &i;
if ( some_condition )
break;
...
}
printf( "last value of i was %d\n", *p );
不能保证达到您的预期。
实际上,生成的机器代码会在函数入口处为i
留出一次space;但是,您不应该依赖这种行为。
代码片段:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
变量i
每次重新开始循环时都存储在堆栈中?
运行这段代码的内存结构是什么?
这个变量的行为是什么?
这样做是坏习惯还是好习惯?
谢谢。
你永远达不到i == 500.
因为它在while(1){}.
以下将起作用。
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
在此代码中,变量 i 将始终为 0 或 1;中断永远不会执行。
变量 i 在 while 循环中声明并且是局部的。
在C语言中,一对大括号可以创建一个新的作用域 隐藏在外部声明的同名变量 范围。
此代码:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
应该改成这样:
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
当 C 中的函数 运行 时,它会为所有需要的局部变量分配 space。如果变量在函数顶部彼此相邻分配,则很容易看出它是如何工作的:
void foo(){
int x;
int y;
y = 1;
x = y + 2;
return x + y;
}
如果变量是在函数的内部块内声明的,编译器所做的是 "lift" 将那些变量声明到函数的顶部。如果存在名称冲突的变量,编译器会为您重命名,以便它们引用正确的变量。
// This is what you write
void original(){
int x = 0;
while(1){
int x = 1;
}
}
// This is what the compiler "sees"
void lifted(){
int x1;
int x2;
x1 = 0;
while(1){
x2 = 0;
}
}
在您的例子中,您的代码表现如下:
void function(void)
{
int i;
while(1)
{
i = 0;
i += 1;
if(i == 500) break;
}
}
在这个版本中,很明显 i 一直被重置为 0,这就是循环将永远 运行 的原因。
至于在内部范围内声明变量是否是一个好习惯,它与内存使用无关,而与变量名的范围有关。一般来说,如果可能的话,将变量限制在内部范围内是一件好事(出于与局部变量优于全局变量的相同原因)。也就是说,您始终必须在循环之前而不是在循环内部初始化变量。在这种情况下,它是关于消除错误而不是成为最佳实践。
从逻辑上讲,循环的每次迭代都会创建一个 i
变量的新实例,该实例仅存在于循环体内。正如所写,这段代码永远不会终止,因为 while
循环的每次迭代都会创建一个 i
的新实例并将其初始化为 0
.
尝试在循环体外部引用 i
会导致未定义的行为; IOW,代码像
int *p;
while ( 1 )
{
int i = 0;
p = &i;
if ( some_condition )
break;
...
}
printf( "last value of i was %d\n", *p );
不能保证达到您的预期。
实际上,生成的机器代码会在函数入口处为i
留出一次space;但是,您不应该依赖这种行为。