c语言全局变量、局部变量和存储类别

                              第十二次课----全局变量、局部变量和存储类别
一、作用域
 1.文件作用域
 2.函数作用域
 3.语句块
 demo1: 
 int main(void)
 {
    int a = 0;
    {
       int i = 0;
    }
    i = 10;//错误,i超出了它的作用域范围
    return 0;
 }
 demo2:
 int main(void)
 {
    int a = 0;
     for(int i = 0;i < 5;i++)//i是语句块作用域
    {
       
    }
    i = 10;//错误,i超出了它的作用域范围,
    return 0;
 }
 注意:
 1>同一个作用域中不能出现相同的标识符(黑色单词,如变量名,函数名)
 demo:
void foo(int a)
{
   int a = 0;//错误,a重定义
}

void foo(void)//错误,foo重定义
{
   int foo= 0;//正确
}
 2>函数作用域嵌套在文件作用域内,语句块作用域嵌套在函数作用域内。
 demo:
//文件作用域
void foo(void)//函数作用域
{
   int  a = 0;
   for(int i = 1; i < 10; i++)//语句块作用域
   {
   }
}
3>判定标识符属于哪一个作用域的原则是:就近原则
  标识符不能同时属于两种作用域!
demo
void foo(void)
{
   int  i = 0;
   for(i = 1; i < 10; i++)//语句块作用域
   {
        int i  = 10;
        printf("%d\n", i);
   }
   printf("%d\n", i);
   int foo = 10;
   printf("%d", foo);//是函数名还是变量名??
}

demo2分析下面变量的作用域
float f1(int a)
{
    int b = 0,c = 0;//a,b,c在f1中有效
}
float f2(int x,int y)
{
    int i = 0,j = 0;//x,y,i,j在f2有效
}
int main()
{
    int m = 0,n = 0;//m,n只在main 函数中有效
    return 0;
}
4>
局部变量:就是在函数作用域或者是语句块作用域中定义的变量
全局变量:就是在文件作用域中定义的变量(实际开发中尽量不要使用全局变量)
demo识别以下变量是局部变量还是全局变量
int g_a = 0;
void foo(void)
{
   int  i = 0;
   for(i = 1; i < 10; i++)
   {
        int i  = 10;
        printf("%d\n", i);
   }
   printf("%d\n", i);
   int foo = 10;
   printf("%d", foo);
}
int foo = 0;//error
总结:
作用域解决的是标识符的使用范围,是空间的问题
5>全局变量和函数都属于文件作用域内的标识符,文件作用域内的标识符是可以通过extern扩展作用域的!
demo1 指出下面程序的错误
int main(void)
{
   foo();//error
   printf("%d", g_a);//error
   return 0;
}
void foo(void){}
int g_a = 0;

改进如下
extern void foo(void);
extern int g_a = 0;
int main(void)
{
   foo();//error
   printf("%d", g_a);//error
   return 0;
}
void foo(void){}
int g_a = 0;

 二、存储类别
 1.存储类别解决的是标识符的“生命周期”或者变量内存的开辟时间和销毁时间
 2.学习存储类别时不要去考虑作用域,两者没有关系!

 void foo(int a)
 {
    int b = 0;
 }//a内存销毁
 int main(void)
 {
    foo(10);//a内存开辟
    return 0;
 }

 三、栈变量:auto声明的变量
 变量内存开辟时间:栈变量是在执行到变量定义语句时开辟内存
 变量内存销毁时间:所在作用域结束后销毁
 void foo(int a)
 {
    int b = 0;//b开辟内存
    {
       int i = 0;//i开辟内存
    }//i内存销毁
    i = 10;//错误,i内存已经销毁
 }//b内存销毁,a内存销毁
 int main(void)
 {
    foo(10);//a开辟内存
    foo(20);//a重新开辟内存
    return 0;
 }
 
 注意:只有局部变量可以用auto修饰,全局变量不行,默认情况下是可以省略。
 demo:
 auto int a = 0;//错误,a是全局变量不能用auto修饰
 int main(void)
 {
     auto int i = 0;
     int b = 0;
 }
 
 四、全局区变量:用static声明的变量
 变量内存开辟时间:编译时
 变量内存销毁时间:主函数结束时
 
 void foo(int a)
 {
    static int b = 0;//b编译时开辟内存,该语句只在编译时执行一次,后面不再执行
    {
       int i = 0;//i开辟内存
    }//i内存销毁
    b++;
    printf("%d\n",b);
 }//a内存销毁
 int main(void)
 {
    foo(1);//a开辟内存
    foo(2);//a重新开辟内存
    return 0;//主函数结束时b销毁内存
 }

 注意:1>并非所有的变量都可以声明为static,形式参数不能声明为static,只能声明 为auto.
 void foo(static int a);//错误,形参a不能用static声明
 void foo(auto int a);//正确
 2>变量声明为static时,不赋初值时默认为0.
 void foo(void)
{
   static int count;//默认是0
   count++;
   printf("%d", count);
}
int main(void)
{
   foo();
   foo();
   foo();
   return 0;
}
 3>全局标识符如果用static修饰,并不是表示在全局区而是表示该标识符只能在本文件内被扩展使用。
 demo1:
main.c:
extern  int g_a;//正确
static int g_a;

fun.c
extern  int g_a;//错误

demo2.
main.c:
extern void foo(void);//正确
static void foo(void){};
fun.c
extern void foo(void);//错误

猜你喜欢

转载自blog.csdn.net/qq_41992378/article/details/82731869