当前位置: 首页 > news >正文

013作用域

一、基本概念

C语言中,标识符都有一定的可见范围,这些可见范围保证了标识符只能在一个有限的区域内使用,这个可见范围,被称为作用域(scope)。

软件开发中,尽量缩小标识符的作用域是一项基本原则,一个标识符的作用域超过它实际所需要的范围时,就会对整个软件的命名空间造成污染,导致一些不必要的名字冲突和误解。

例子:
    你在一个工程里,定义了一个全局变量int num,那么接下来工程里面所有的
    区域,你都将要注意,定义变量时,不能和其产生冲突或者误解

二、函数声明作用域

  • 概念:在函数的声明式中定义的变量,其可见范围仅限于该声明式。
  • 要点:
  • 变量 num1 和 num2 只在函数声明式中可见。
  • 变量 num1 和 num2 可以省略,但一般不这么做,它们的作用是对参数的注解。
  • 示例代码
#include <stdio.h>

// (1)、函数声明作用域:
extern int func1(int num1, int num2);  // 变量只作用在这一行
extern int func2(int, int);            // 上面的语句可以写成这样,但一般不建议,因为变量名可以为我们提供参考


int main(int argc, char const *argv[])
{
    // (1)、在函数的声明式中定义的变量,其可见范围仅限于该声明式
    // num1 = 100;
    /*
        会报错:
            main.c:11:5: error: ‘num1’ undeclared (first use in this function)
                num1 = 100;
                ^  
        原因:
            1、你真的没有定义这个变量num1
            2、你定义了,但是num1变量,没能作用在你现在处在的内存区域中
    */

    
    
    return 0;
}

三、局部作用域

  • 概念:在代码块中定义的变量,其可见范围从其定义处开始,到代码块结束为止。
  • 要点:
  • 代码块指的是一对花括号 { } 括起来的区域。
  • 代码块可以嵌套包含,外层的标识符会被内嵌的同名标识符临时掩盖变得不可见。
  • 代码块作用域的变量,由于其可见范围是局部的,因此被称为局部变量。
  • 示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int num2 = 100;                  // 存储与栈空间,作用于本函数(main)的{}括号里面
    
    { 
        int num2 = 200;             // 存储与栈空间,作用于包括它的{}括号里面
    
        {
            int num2 = 300; 
            num2 = 666;             // 优先使用最靠近它的{}括号(外层的标识符会被内嵌的同名标识符临时掩盖变得不可见)
            printf("num2(第三层) = %d\n", num2); 
        }
    
        printf("num2(第二层) = %d\n", num2); 
    
    }
    printf("num2(第一层) = %d\n", num2);    // printf函数因为在main函数的{}括号里,所以其打印的是作用范围在main函数的{}括号里num2变量
    
}

四、全局作用域

  • 概念:在代码块外定义的变量,其可见范围可以跨越多个文件。
  • 要点:
  • 全局变量作用域在整个程序中,因此称其为全局变量
  • 如果a文件想要访问b文件的全局变量,需要在a文件函数体外,使用extern关键字在变量前面 进行修饰
  • 如果一个文件里的全局变量,只想作用于本文件,则在其前面加上static即可
  • 图解:

  • 示例代码:

main文件:

#include <stdio.h>
// 全局变量定义
int num3;                                // 存储与数据段的bss段中, 普通全局变量,跨文件可见(整个工程的文件都可以看到这个变量)
int num4 = 400;                          // 存储与数据段的data段中,普通全局变量,跨文件可见(整个工程的文件都可以看到这个变量)
static int num5;                         // 存储与数据段的bss段中, static全局变量,本文件可见(工程的其它文件不可以看到这个变量)
static int num6 = 600 ;                  // 存储与数据段的data段中,static全局变量,本文件可见(工程的其它文件不可以看到这个变量)

// 全局函数声明
extern void a_func_1(void);              // 代码区(没有内存空间,只是一段跳转地址)

int main(int argc, char const *argv[])
{
    num3 = 333;
    num4 = 444;
    printf("num3 = %d\n", num3);
    printf("num4 = %d\n", num4);
    

    // a_func_1();
    /*
        报错:
            a.c:(.text+0x27): undefined reference to `num5'
            a.c:(.text+0x31): undefined reference to `num5'
        原因:
            num5和num6由于在其它文件(a.c)不可见,其它文件(a.c)又调用了,这样会报错了
    */
}

a.c文件

#include <stdio.h>
/*
    说明:
        对于函数:
            extern可以省略的,依然还是表示函数声明(因为你可以轻而易举的区分出谁
            是定义,谁是声明(有多条语句的就是定义,只有一条语句并且还有结束符;号的就是声明))
        对于全局变量:
            extern不可以省略的,因为可能会将其当成定义来对待(尤其是你没有初始化的时候)

    总结(给大家的建议):
        不论是函数,还是全局变量,都用extern来声明,不要省略不写

*/
// 全局变量声明
extern int num3;    // 代码区,在本文件可见
extern int num5;    // 代码区,在本文件不可见(因为main函数使用static进行了修饰,掩盖了这个变量,所以找不到了)

// 全局函数定义
void a_func_1(void) // 既是在代码区(代码文本+跳转地址),又在栈区(函数的具体内容)
{
    num3 = 100;
    printf("num3 = %d\n", num3);

    num5 = 555;
    printf("num5 = %d\n", num5);
}

五、作用域的临时掩盖

如果有多个不同的作用域相互嵌套,那么小范围的作用域会临时 “遮蔽” 大范围的作用域中的同名标识符,被 “遮蔽” 的标识符不会消失,只是临时失去可见性。

  • 示例代码:
int a = 100;

// 函数代码块1
int main(void)
{
    printf("%d\n", a); // 输出100
    int a = 200;
    printf("%d\n", a); // 输出200
   
    // 代码块2 
    {
        printf("%d\n", a); // 输出200
        int a = 300;
        printf("%d\n", a); // 输出300
    }
    printf("%d\n", a); // 输出200
}

void f()
{
    printf("%d\n", a); // 输出100
}

六、static关键字

C语言的一大特色,是相同的关键字,在不同的场合下,具有不同的含义。static关键字在C语言中有两个不同的作用:

  1. 将可见范围设定为标识符所在的文件:
  • 修饰全局变量:使得全局变量由原来的跨文件可见,变成仅限于本文件可见。
  • 修饰普通函数:使得函数由原来的跨文件可见,变成仅限于本文件可见。
  1. 将存储区域设定为数据段:

修饰局部变量:使得局部变量由原来存储在栈内存,变成存储在数据段。

  • 示例代码:
    int a; // 普通全局变量,跨文件可见
static int b; // 静态全局变量,仅限本文件可见

void f1()        // 普通函数,跨文件可见
{}

static void f2() // 静态函数,仅限本文件可见
{}

int main()
{
           int c; // 普通局部变量,存储于栈内存
    static int d; // 静态局部变量,存储于数据段
}

至此,希望看完这篇文章的你有所收获,我是Bardb,译音八分贝,道友,下期见!

相关文章:

  • php特性
  • c++ 中的容器 vector 与数组 array
  • wzl-django学习
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_buf_t
  • MAVEN的安装和配置指南【超详细】
  • 《Web安全渗透测试实战:DVWA靶场全关卡通关指南(高/中/低/不可能级别)|手把手教你掌握漏洞挖掘与渗透技巧》
  • 图像仿射变换
  • 计算机黑皮书191本分享pdf
  • 卷积神经网络(cnn,类似lenet-1,八)
  • ETL系列-数据抽取(Extract)
  • [AI 概念域] LangChain 生态工具概念解读(通俗解读)
  • [Linux]项目自动化构建工具-make/Makefile
  • 跟我学C++中级篇——定时器的设计
  • 初阶数据结构(C语言实现)——3顺序表和链表(3)
  • 《第十五部分》STM32之FLASH闪存(终结篇)
  • (九)趣学设计模式 之 桥接模式!
  • 综合练习 —— 递归、搜索与回溯算法
  • 第十五届蓝桥杯单片机组4T模拟赛三(第二套)
  • 区县级水司一体化抄表营业收费系统设计思路
  • Datawhale 数学建模导论二 笔记5 多模数据与智能模型
  • 住房公积金网站怎么做减员/产品营销
  • 宁波网站推广厂家电话/seo综合查询网站源码
  • 设计的网站都有哪些功能/百度平台订单查询
  • 怎么在备案号添加网站/如何自己开发一个网站
  • 网站不备案可以做淘宝客吗/搜索引擎营销方法有哪些
  • 网站智能云/长沙网络营销顾问