• 深入理解关键字 一(auto,register,static,sizeof)



    在这里插入图片描述

    32个关键字

    在c89,c90中存在32个关键字。

    数据类型关键字(12个)
    char :声明字符型变量或函数
    short :声明短整型变量或函数
    int : 声明整型变量或函数
    long:声明长整型变量或函数
    signed :声明有符号类型变量或函数
    unsigned :声明无符号类型变量或函数
    float:声明浮点型变量或函数
    double :声明双精度变量或函数
    struct :声明结构体变量或函数
    union :声明共用体(联合)数据类型
    enum :声明枚举类型
    void :声明函数无返回值或无参数,声明无类型指针

    控制语句关键字(12个)

    1. 循环控制(5个)

    for :一种循环语句
    do :循环语句的循环体
    while :循环语句的循环条件
    break :跳出当前循环
    continue :结束当前循环,开始下一轮循环

    1. 条件语句(3个)

    if : 条件语句
    else :条件语句否定分支
    goto :无条件跳转语句

    1. 开关语句 (3个)
      switch :用于开关语句
      case :开关语句分支
      default :开关语句中的“其他”分支
    1. 返回语句(1个)
      return :函数返回语句(可以带参数,也看不带参数)

    存储类型关键字(5个)
    auto :声明自动变量,一般不使用
    extern :声明变量是在其他文件中声明
    register :声明寄存器变量
    static :声明静态变量
    typedef :用以给数据类型取别名(但是该关键字被分到存储关键字分类中,虽然看起来没什么相关性)

    其他关键字(3个)
    const :声明只读变量
    sizeof :计算数据类型长度
    volatile :说明变量在程序执行中可被隐含地改变

    🛺auto

    🍕变量

    🤔为什么要存在变量?

    计算机对数据进行计算是在CPU内完成的,CPU在处理数据的时候是一个数据一个数据的处理,并不是一下子将所有的数据就处理完了,就好比人吃饭一样,是一口一口的吃。

    这个时候就能体现变量的作用了。既然CPU是一个数据一个数据的处理,那些还未处理的数据该如何做呢?当然是通过变量存储起来,需要使用的时候,再去将这个变量传到CPU内。

    那这个时候就可以回答上面的问题了。变量存在的意义是存储数据,以供后续使用

    🤔变量定义的本质是什么

    既然知道了变量的意义,是用来存数据的,那是不是需要空间呢?当然需要。
    定义变量的本质是开辟空间,存储数据

    需要强调一点,定义只能一次,换句话说,同一个变量只能定义一次,不可以多次定义同一个变量。

    在哪开辟空间呢?在内存中开辟空间。

    ✨局部变量和全局变量

    什么是局部变量?
    在函数内部或者在{}中定义的变量就叫做局部变量。
    那全局变量呢?
    在所有函数外部定义的变量叫全局变量。

    🎈变量的生命周期

    什么是生命周期?从变量定义开始,到变量释放,这一时间段就是变量的生命周期。

    🎈局部变量的生命周期

    上面有说到,局部变量是在函数内部或者{}定义的变量叫做局部变量。生命周期如何体现呢?
    我们来看下图的红色波浪线,以及报错

    在这里插入图片描述
    在这里插入图片描述

    总结
    局部变量的生命周期:进入代码块,形成局部变量[开辟空间],退出代码块,"释放"局部变量

    至于局部变量为什么要释放,这跟它存储位置有关,局部变量存放在栈区,栈区的存放的变量是具有临时性,也就是会释放它所占有的空间。
    那局部变量的生命周期就很好理解了,只在它定义的范围内有效。

    可以在通过一个例子来理解

    在这里插入图片描述

    可以看到打印结果是0,1,0,1的重复。这是因为test函数中的变量i在不断的定义和释放。

    在这里插入图片描述

    🎈全局变量的生命周期

    看到“全局”二字,我们就有所猜测了。
    全局变量的生命周期是跟随程序的整个进程。也就是说只要程序存在,全局变量就“活”着。

    这也和全局变量的存储位置有关,它存放在全局数据区,放在全局数据区的数据,都是会和程序”同生共死“。

    在这里插入图片描述

    🎈变量的作用域

    作用域是指该变量的可以被正常访问的代码区域。
    也可以这样理解,作用域是该变量能够影响的范围。

    局部变量:只在本代码块内有效
    全局变量:整个程序运行期间,都有效

    看到这你可能会疑惑,感觉生命周期和作用域是一个东西,其实不是。待会讲到static,在去讲这两者会更好理解。

    ✨铺垫做完,auto开始

    aoto是用来修饰局部变量的,全局变量不可被aoto修饰。
    一般都是被省略的。
    这个关键字很老了,已经“退休”了,一般不怎么使用

    在这里插入图片描述
    在这里插入图片描述

    🚗register

    🎈铺垫工作:存储分级

    知道为什么所有人都买得起电脑吗?是因为存储分级的存在,电脑的价格才降下来的。

    在这里插入图片描述

    我们知道CPU是对数据进行计算的,在计算的时候,CPU一般先从内存中读取数据。读取过来的数据,需要存放,所以CPU是具备一定的存储能力,即通过寄存器来存储这些数据。
    寄存器离CPU很近,那么每次CPU获取数据的时候就会很快。

    这些和register有什么关系吗?有关系。

    💡register作用

    可以称register是“最快的男人” ,register修饰变量的作用:尽量将这个变量,存到寄存器中,从而达到提高效率的目的。

    哪些变量可以使用register呢?
    1.局部变量(全局变量不可使用,因为生命周期随着程序进程,会导致寄存器长期占用)
    2.高频使用的变量
    3.不需要写入的数据(写入就需要回内存,这样用register修饰还有何意义呢)
    如果使用register,不能高频使用,因为寄存器有限。

    🤔register修饰的变量能被取地址吗?

    答案是不能,地址是内存特有的概念,寄存器不属于内存。

    在这里插入图片描述

    🚕static

    ✨铺垫工作

    🤔变量和函数可以跨文件使用吗?

    答案是可以!

    在这里插入图片描述
    在这里插入图片描述

    函数为什么可以不声明?

    程序翻译过程是:预处理–>编译–>汇编–>链接–>可执行二进制文件。

    我们只需要了解链接即可,链接的过程是将多个文件整合在一起的过程。
    这里是将 test.c,test2.c和stdio.h整合在一起。
    test.c中主函数中调用show函数的时候没有找到,但是在链接后,可以找到show这个函数,所以可以调用它。

    全局变量如果不声明的话,是会报错的,还没走到链接这一环节,就报错了。

    所以函数和变量是可以跨文件使用的!
    一般的我们也要将函数的声明写上。

    🎈头文件的引入

    假如现在有一百多个文件,一百多个文件中都有全局变量,和函数。

    这一百多个文件中每个文件要使用其他文件的函数和全局变量,那每个文件中,都需要写对应函数变量的声明。

    声明还好,如果你对函数或者全局变量进行修改,那么对应的声明也要修改,这样的维护成本太高。

    为了解决这个问题就引入了头文件。头文件里放声明,其他文件来引用这个头文件,那么维护成本就大幅度降低。

    那头文件(自定义的头文件)一般都放些什么呢?
    1.头文件(库函数的头文件)
    2.函数声明,全局变量的声明
    3.宏定义
    4.结构体,联合体,枚举

    在这里插入图片描述

    右击–>添加–>新建项–>选中头文件

    在这里插入图片描述
    在这里插入图片描述

    头文件的引用,自定义头文件的一般使用“”,库函数的头文件一般用<>。

    在vs2019中新建一个头文件
    会默认有一段代码#pragma once这是一个预处理命令,作用是防止头文件被多次引用。
    如果没有这段代码,可以手动加上。
    三子棋、五子棋多文件实例

    💡static修饰全局变量和函数

    我们已经知道了,全局变量和函数是可以跨文件的,如果我不想让它们跨文件该如何?就是用static修饰。

    🎈static修饰全局变量

    作用是改变了全局变量的作用域,只能在本文件中有效。外部文件不能直接使用,全局变量的生命周期没改变!

    在这里插入图片描述

    🎈static修饰函数

    作用是该函数只能在本文件中有效,外部文件不能直接使用。

    在这里插入图片描述

    🎈static修饰局部变量

    static修饰局部变量的作用是:改变该变量的生命周期,由局部的变为全局性的。但是作用域没有改变!

    这个时候就可以很好的区分生命周期和作用域的概念了

    在这里插入图片描述
    在这里插入图片描述

    第一张图:k在不断的定义释放,所以结果都是1。(进函数定义,出函数销毁)
    第二张图:我们可以看到定义只发生了一次,没有被销毁!

    为什么说只定义了一次,没有被销毁?因为打印的时候1只出现了一次,也就验证了上述所说的。

    这里就是生命周期发生改变了,从原来的临时性变为全局性。
    相应的存储位置也发生了变化。由原来的栈区存储,改为在全局数据区存储。

    通过下面一张图来看看,作用域发生改变了没有。

    在这里插入图片描述

    可以发现作用域是没改变的,尽管k的生命周期变成了全局性,但是它影响的范围只在test函数中,也是其对应的代码块内。

    🚌sizeof

    sizeof的作用是求元素类型的大小。元素的类型不仅仅是指int,double,这类内置类型,也包括其他复杂类型。
    比如说,int(*)[10], int[10]…

    🎈sizeof返回值的问题

    其次要注意sizeof的返回值类型是 unsigned int 通过下面题带你理解

    在这里插入图片描述

    因为sizeof返回的结果是无符号的,在和i进行运算的时候中间发生了算数转换。i从原来的有符号整形提升为无符号整形。

    🤔sizeof 是函数吗?

    sizeof不是函数,是关键字,也可以说是操作符。

    在这里插入图片描述

    验证了sizeof求的是类型的大小。

    在这里插入图片描述

    两个关键字不可以连用,需要带上()

    在这里插入图片描述

    验证了sizeof不是函数! 因为函数需要()

    🤔sizeof中的表达式计算吗?

    在这里插入图片描述

    答案是不计算,为什么呢?上面有讲到程序的翻译过程
    预处理–>编译–>汇编–>二进制可执行程序。
    sizeof在编译的时候,就能知道类型的大小,并且将计算的结果赋值给b,在编译后面的环节中,就没有sizeof了,所以sizeof它压根不在意表达式是什么。

    🎉总结

    auto是用来修饰局部变量的,一般省略。

    register作用是尽量将修饰的变量,放到寄存器中,提高效率。

    static修饰全局变量,该变量的作用域发生改变,生命周期未改变,只在本文件中使用,不能被外部文件直接使用。

    static修饰函数,该函数只能在本文件中使用,不能被外部文件直接使用。

    static修饰局部变量,该变量的生命周期变为全局生命周期,但其作用域未发生改变。

    sizeof求元素类型所占的空间大小,单位是字节。

  • 相关阅读:
    OpenCV-最小外接圆cv::minEnclosingCircle
    Spire.PDF for .NET 9.8.5 Crack
    Xilinx 千兆以太网TEMAC IP核简介
    python将xml格式文件转成png或者pdf格式
    【Flutter】IOS运行工程二次启动崩溃问题。
    TypeScript入门
    基于java的空巢老人管理系统
    Vue组件之间通信
    计算机组成原理知识总结(五)中央处理器
    平行港口:智慧绿色时代下港口工业智联网新形态与体系结构
  • 原文地址:https://blog.csdn.net/m0_64212811/article/details/127000077