C语言之变量作用域

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言之变量作用域相关的知识,希望对你有一定的参考价值。

参考技术A 全局变量:作用域整个工程,在使用的地方通过extern声明即可,存放于全局数据区,占用静态存储单元。

局部变量:作用于函数方法体内,函数执行结束就释放,存放于栈区。

全局静态变量:作用于当前类,在外部类不可使用,除非使用#include引入头文件,存放于全局数据区。

局部静态变量:作用于函数方法体内,函数执行结束不释放,存放于全局数据区。

全局静态存储区:分为 DATA 段和 BSS 段。DATA 段(全局初始化区)存放初始化的全局变量和静态变量;BSS 段(全局未初始化区)存放未初始化的全局变量和静态变量。程序运行结束时自动释放。其中BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。

静态存储变量的优势:

优势: 可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。

关于static

(1)在修饰变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。

(2)static 修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。

(3)static 修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,都在全局数据区分配内存。初始化的时候自动初始化为 0。

(4)不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用 static 修饰。

(5)考虑到数据安全性(当程序想要使用全局变量的时候应该先考虑使用 static)。

嵌入式bug粉碎机之C语言变量作用域的坑


1、聊一聊

This browser does not support music or audio playback. Please play it in Weixin or another browser. 【嵌入式】bug粉碎机之C语言变量作用域的坑

    今天分享的歌曲名称是"年少轻狂"的意思,一听开头就是一个好歌!当然经典的还是这句"my youth is yours".


    文章跟大家分享下C语言变量作用域的一个总结,这块对于编程老手而言,再简单不过了, 不过这中间还是会有一些有意思的问题。


【嵌入式】bug粉碎机之C语言变量作用域的坑


3、C语言变量作用域

    

    这个话题主要是受交流群里面小哥的调试分享,感觉这块虽然简单,不过还蛮有意思的,所以总结分享给大家。


【嵌入式】bug粉碎机之C语言变量作用域的坑

    

    C语言变量总的来说主要分为 : 全局变量;静态全局;局部变量;静态局部。


    然而奇妙的一点是这些变量可以使用相同的变量名,编译器却可以正确识别和编译的主要原因是他们有各自不同的作用域,从而让编译器能够正确区分。




作用域




  • 全局变量 :  一旦定义和声明了即可供程序访问;

  • 静态全局:一旦定义和声明了即在文件中访问;(静态全局如何声明?)

  • 静态局部:仅在{}代码块之间进行访问;

  • 局部变量:仅在{}代码块之间进行访问;


    这里理论规则bug菌就讲这么多,把一些细节通过后面的代码说明一下。


2、作用域细节


【嵌入式】bug粉碎机之C语言变量作用域的坑
同名变量谁更强

 1///////File : main.c
2#include <stdio.h>
3#include <stdlib.h>
4#include "Fuc.h"
5
6int bug = 111;    //全局变量 
7
8/********************************
9 *Fuction: 测试变量作用域
10 *Author :(公众号:最后一个bug) 
11 ******************************/
 
12int main(int argc, char *argv[])
13{
14   printf("bug1 = %d\n",bug);
15   Fuction();
16   return 0;
17}
18
19
20///////File : Fuc.c
21#include <stdio.h>
22#include <stdlib.h>
23#include "Fuc.h" 
24
25//static int bug = 222; 
26
27extern int bug; 
28/********************************
29 *Fuction: 测试变量作用域 Fuction
30 *Author :(公众号:最后一个bug) 
31 ******************************/
 
32void Fuction(void)
33{
34    printf("bug2 = %d\n",bug);
35    if(bug > 0)
36    {
37       int bug = 333;
38       printf("bug3 = %d\n",bug);
39       if(bug > 0)
40       {
41         int bug = 444;
42         printf("bug4 = %d\n",bug);
43       }
44
45    }
46}
47
48///////File : Fuc.h
49#ifndef __FUC_H__
50#define __FUC_H__
51
52extern void Fuction(void);
53
54#endif  
输出结果:

【嵌入式】bug粉碎机之C语言变量作用域的坑

分析一下:

     上面bug菌在DevC++5.7上面运行的结果,虽然全部用的bug变量,大部分小伙伴应该都能够得到正确的结果,其中bug2当然使用的是全局变量了。


     然而我们把文件Fuc.c中间的static bug = 222;放开注释,可以得到如下结果:


【嵌入式】bug粉碎机之C语言变量作用域的坑


     其输出结果表明编译器会优先选择静态全局变量来进行处理而非外部全局。

易错点

     

    对于编程习惯不是很好的小伙伴,在很久以前留了一个静态的全局bug变量在文件的开头或者其他地方,然而程序中又正在使用一个同名的全局变量试图在外部修改,然后在本文件中使用,此时就会发现根本没法通过外部修改影响到内部状态,因为你修改的外部全局变量根本就不是本文件中的同名变量。


   当然如果你能够直接在线仿真还是能够比较容易找到该问题,毕竟停下来以后鼠标点到两个名字会有不同的值;所以编程习惯比较好的小伙伴应该大部分不会遇到该问题。


    所以也不建议大家在程序中定义相同的变量名称,并且变量定义后者声明尽量比较集中。


作用域总结



通过上面的程序,我们可以一句话总结变量作用域 : 谁管辖的范围小,从定义/声明开始处谁最大。




【嵌入式】bug粉碎机之C语言变量作用域的坑
静态变量声明易错


    下面的代码仅仅只是在前面的Fuc.c文件做了一下简单的修改,用于说明静态变量的声明:


 1#include <stdio.h>
2#include <stdlib.h>
3#include "Fuc.h" 
4
5
6static int bug;  //声明 
7
8
9/********************************
10 *Fuction: 测试变量作用域 Fuction
11 *Author :(公众号:最后一个bug) 
12 ******************************/
 
13void Fuction(void)
14{
15    printf("bug2 = %d\n",bug);
16    if(bug > 0)
17    {
18       int bug = 333;
19       printf("bug3 = %d\n",bug);
20       if(bug > 0)
21       {
22         int bug = 444;
23         printf("bug4 = %d\n",bug);
24       }
25
26    }
27}
28
29
30
31static int bug = 222//定义 
32
33/********************************
34 *Fuction: 测试变量作用域 Fuction
35 *Author :(公众号:最后一个bug) 
36 ******************************/
 
37void Fuction2(void)
38{
39    printf("bug5 = %d\n",bug);
40    if(bug > 0)
41    {
42       int bug = 333;
43       printf("bug6 = %d\n",bug);
44       if(bug > 0)
45       {
46         int bug = 444;
47         printf("bug7 = %d\n",bug);
48       }
49
50    }
51}
分析一下:

     上面分别是静态变量的声明和定义,你可能会发现这里的静态变量的声明和未初始化的静态全局变量定义是一样的。


    如果你习惯给静态变量初始化编译器会报重复定义,如果你不习惯初始化,如果时间久了,代码不规范, 还一直认为该变量初始化默认是0,其实后面的定义初始化就引入了bug隐患。


    同时大家还可以尝试在函数内部extern,或者在其他编译器里面来定义并使用同名变量,你会发现更多有意思的地方,同时也是大家需要注意的地方,最终规避掉这些问题还是需要有良好的编程习惯!


3、最后小结

     该部分就这点内容吧,比较简单、也不多,或许以后会是查找bug的一个方向,毕竟在公司里面一般一套代码不是一个人开发,各种bug都是有可能遇到的。


推荐好文  点击蓝色字体即可跳转

【嵌入式】bug粉碎机之C语言变量作用域的坑

【嵌入式】bug粉碎机之C语言变量作用域的坑

最后一个bug 发起了一个读者讨论 你还遇到什么bug,欢迎和大家交流讨论!! 精选讨论内容
bug菌(未知bug)

以上是关于C语言之变量作用域的主要内容,如果未能解决你的问题,请参考以下文章

C语言中 变量作用域的区别

C语言“局部变量作用域”的问题

关于C语言作用域

c语言作用域

C语言之程序结构

初识C语言