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

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

深入理解关键字

  • 32个关键字
  • 🛺auto
    • 🍕变量
      • 🤔为什么要存在变量?
      • 🤔变量定义的本质是什么
    • ✨局部变量和全局变量
      • 🎈变量的生命周期
        • 🎈局部变量的生命周期
        • 🎈全局变量的生命周期
      • 🎈变量的作用域
    • ✨铺垫做完,auto开始
  • 🚗register
    • 🎈铺垫工作:存储分级
    • 💡register作用
      • 🤔register修饰的变量能被取地址吗?
  • 🚕static
    • ✨铺垫工作
      • 🤔变量和函数可以跨文件使用吗?
      • 🎈头文件的引入
    • 💡static修饰全局变量和函数
      • 🎈static修饰全局变量
      • 🎈static修饰函数
      • 🎈static修饰局部变量
  • 🚌sizeof
    • 🎈sizeof返回值的问题
    • 🤔sizeof 是函数吗?
    • 🤔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求元素类型所占的空间大小,单位是字节。

相关文章:

  • 基于Springboot+vue的停车场管理系统(Java毕业设计)
  • 详解CAN总线:CAN总线报文格式—数据帧
  • mysql进阶:canal实现mysql数据同步到redis|实现自定义canal客户端
  • React路由三种渲染方式、withRouter高阶组件、自定义导航组件
  • FaceNet-pytorch(fixing data imbalance-CASIA)
  • 【内核的设计与实现笔记】| 【01】初步了解内核
  • 【HDLBits 刷题】所有答案直达链接汇总
  • portswigger 目录遍历文件上传
  • 【微信小程序入门到精通】— swiper 超详细的属性值讲解!确定不来看看?
  • [单片机框架][device层] fuelgauge 电量计
  • 基于linux的web服务器(问题)
  • 【leetcode top100】两数相加。无重复字符的最长子串,盛水最多的容器,三数之和
  • PIE-Engine 教程:水稻面积提取1(宿迁市)
  • CMSC5707-高级人工智能之语音识别
  • AES(对称加密)学习记录
  • 【391天】每日项目总结系列128(2018.03.03)
  • Django 博客开发教程 8 - 博客文章详情页
  • ES6简单总结(搭配简单的讲解和小案例)
  • ESLint简单操作
  • happypack两次报错的问题
  • JAVA SE 6 GC调优笔记
  • JAVA 学习IO流
  • springMvc学习笔记(2)
  • Tornado学习笔记(1)
  • vuex 学习笔记 01
  • Vultr 教程目录
  • 记录:CentOS7.2配置LNMP环境记录
  • 数据科学 第 3 章 11 字符串处理
  • 数组大概知多少
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 在Mac OS X上安装 Ruby运行环境
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​香农与信息论三大定律
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • !$boo在php中什么意思,php前戏
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (arch)linux 转换文件编码格式
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (分布式缓存)Redis哨兵
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (四)c52学习之旅-流水LED灯
  • (译)计算距离、方位和更多经纬度之间的点
  • .Net 6.0 处理跨域的方式
  • .NET Core 成都线下面基会拉开序幕
  • .Net Core 中间件验签
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .net framework profiles /.net framework 配置
  • .net打印*三角形
  • .Net的C#语言取月份数值对应的MonthName值
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • .stream().map与.stream().flatMap的使用
  • @Query中countQuery的介绍
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...