C语言基础篇 —— 5.0 详解C语言变量的四大属性

news2024/9/21 11:10:48

文章目录

  • 概述
  • C语言变量四大属性
    • 存储类
      • 概念解析
      • Linux 内存映像并解析
    • 作用域
      • 概念解析
      • 局部变量的代码块作用域
      • 函数名和全局变量的文件作用域
      • 同名变量的掩蔽规则
    • 生命周期
      • 概念解析
      • 栈变量的生命周期
      • 堆变量的生命周期
      • 数据段、bss段变量的生命周期
      • 代码段、只读段的生命周期
    • 链接属性
      • 概念解析
      • C语言程序的组织架构:多个C文件+多个h文件
      • 编译以文件为单位、链接以工程为单位
      • 三种链接属性:外链接、内链接、无链接
      • 函数和全局变量的同名冲突
      • static的第二种用法:修饰全局变量和函数
  • 结束语


概述

整个系统(Linux系统、uboot)正常启动并长期运行是由很多变量共同作用而成的,类比我们社会的运作也是由于一代又一代的人不断辛勤努力,不断向社会发展贡献自己的价值一样。本文章从四大特征详细了解下这类在系统中不断更新换代的“人们” —— C语言变量。


C语言变量四大属性

C语言四大属性:存储类、作用域、生命周期、链接属性


存储类

概念解析

1、存储类是存储类型,描述C语言变量在何地方存储。
2、内存有多重管理方式:栈、堆、数据段、bss段、.text段
      一个变量的存储类属性就是描述这个变量存储在何种内存段中。
3、局部变量分配在栈上,所以它的存储类就是栈
      显示初始化为非0的全局变量分配在数据段
      显示初始化为0和没有显示初始化(默认为0)的全局变量分配在bss段

Linux 内存映像并解析

Linux 内存模型
在这里插入图片描述
以上是Linux 系统中 内存分区的分布图,将内存地址分为不同的区域用来存储对应的数据内容,以下结合Linux内核模型分布图来了解下这些内存段以及其存储的具体内容。

内存分区说明
内核映射区内核映射区就是将操作系统内核程序映射到这个区域了
对于linux中的每一个进程来说,它都以为整个系统中只有它自己和内核而已。它认为内存地址0xC0000000以下都是它自己的活动空间,0xC0000000以上是OS内核的活动空间。
每个进程都活在自己独立的进程空间中,0 — 3G的空间每个进程是不同的。(因为使用了虚拟地址技术),但是内核是唯一的。
栈内存区存局部变量;函数调用传参过程也会用到栈
文件映射区 文件映射区就是进程打开了文件后,将文件的内容从硬盘读进进程的文件映射区,以后直接在内存中操作这个文件,读写完了后在保存时再将内存中的文件写到硬盘中去。
C语言是不会自动向堆中存放东西,堆的操作完全是程序员自己手工操作的。程序员根据自己的需求申请、使用、释放。
数据段、bss段数据段就是(1)显示初始化为非0的全局变量(2)显示初始化为非0的static局部变量
bss段就是存(1)系那是初始化为0或者未显示初始化的全局变量(2)显示初始化为0或未显示初始化的static局部变量。
代码段、只读数据段代码段就是对应程序中的代码(函数),代码段在linux中称为文本段(.text)
只读数据段就是程序运行期间只能读不能写的数据。
const修饰的常量可能是存在只读数据段的。

作用域

概念解析

1、作用域是描述这个变量起作用的代码范围。
2、C语言变量的作用域规则是代码块作用域。
      意思是这个变量起作用的范围是当前的代码块。代码块就是一对大括号 {} 扩起来的范围,所以一个变量的作用域就是这个变量定义所在的 {} 范围内从这个变量定义开始往后的部分。

局部变量的代码块作用域

1、代码块基本可以理解为一对大括号 {} 括起来的部分。
2、代码块不等于函数,if while for 都有 大括号{}
3、局部变量的作用域是代码块作用域,也就是说一个局部变量可以被访问和使用的范围仅限于定义这个局部变量的代码块中定义式之后的部分。

函数名和全局变量的文件作用域

1、文件作用域就是全局的访问权限,也就是在整个.c文件中都可以访问。这就是平时所说的局部和全局,全局就是文件作用域
2、函数和全局变量的作用域是定义所在的整个.c文件之内定义式之后的部分。

小结:不管是局部变量、全局变量、函数,都要先定义才能使用

同名变量的掩蔽规则

编程中,不可能避免会出现同名变量。变量同名后不一定会出错。
1、如果两个同名变量作用域不同且没有交叠,这种情况下同名没有影响。
2、如果两个同名变量作用域有交叠,C语言规定在作用域交叠范围内,作用域小的一个变量会掩蔽掉作用域大的那种。


生命周期

概念解析

1、生命周期是描述这个变量什么时候诞生(运行时分配内存空间给这个变量)以及什么时候死亡(运行时收回这个内存空间,此后再不能访问这个内存地址,或者访问这个内存地址已经和这个变量无关了)。
2、研究变量的生命周期可以帮助理解程序运行的一些现象、理解C语言的一些规则。

栈变量的生命周期

1、局部变量(栈变量)存储在栈上,生命周期是临时的。临时:代码执行过程中按照需要去创建、使用、消亡的。
2、如一个函数内定义的局部变量,在这个函数每一次被调用时都会创建一次,然后使用,最后在函数返回的时候消亡。

堆变量的生命周期

1、堆内存空间是客观存在的,是由操作系统维护的。程序只是去申请然后使用然后释放。
2、我们只关心程序使用堆内存的这一段时间,所以堆变量生命周期:从malloc申请时诞生,然后使用,直到free时消亡。
3、堆内存在malloc之前和free之后不能再去访问,因此堆内存在实践编程时是被反复的使用的。

数据段、bss段变量的生命周期

1、全局变量的生命周期是永久的。永久:是在程序被执行时诞生,在程序终止时消亡。
2、全局变量所占用的内存是不能被程序自己释放的,所以程序如果申请了过多的全局变量会导致这个程序一直占用大量内存。

代码段、只读段的生命周期

代码段就是函数,它的生命周期是永久的。
代码段不只是代码,还有const类型的常量,还有字符串常量。(const类型的常量、字符常量有时候放在rodata段,有时候放在代码段,取决于平台)


链接属性

概念解析

1、链接属性描述的是程序从源代码到最终可执行程序,经历的过程:编译、链接
2。编译阶段就是把源代码搞成 .o 目标文件,目标文件里面有很多符号和代码段、数据段、bss段等分段。符号就是编程中的变量名、函数名等。运行时变量名、函数名能够和相应的内存对应起来,靠符号来做链接的。
3、 .o的目标文件链接生成最终可执行程序的时候,其实是把符号和相应的段连接起来。C语言中的符号有三种链接属性:外链接属性、内链接属性、无链接属性

C语言程序的组织架构:多个C文件+多个h文件

1、整个而又庞大的C语言程序(linux内核、uboot)由多个C文件和h文件组成的。
2、程序的生成过程:编译+链接
      编译是为了将函数/变量等变量.o二进制的机器码格式
      链接是为了将各个独立分开的二进制的函数链接起来形成一个整体的二进制可执行程序。

编译以文件为单位、链接以工程为单位

1、编译器工作时是将所有源文件依次读进来,单个为单位进行编译的。
2、链接的时候实际上是把第一步编译生成个单个的.o文件整体的输入,然后处理链接成一个可执行程序。

三种链接属性:外链接、内链接、无链接

1、外链接:外部链接属性可以在整个程序范围内进行链接(可以跨文件),如函数和全局变量
2、内链接:内连接属性可以在当前C文件内部范围内进行链接(不能再除当前C文件之外的其他C文件中进行访问、链接)。如static修饰的函数/全局变量属于内链接。
3、无链接:不参与链接属性就是跟链接没有关系。如所有局部变量(auto的、static的)都是无链接的。

函数和全局变量的同名冲突

1、因为函数和全局变量是外部链接属性,就是每个函数和全局变量将来在整个程序中所有的C文件都能被访问,因此在一个程序中的所有C文件中不能出现同名的函数/同名的全局变量。
2、现在高级语言中完美解决这个问题的方法是命名空间namespace(是给一个变量带上各个级别的前缀)
3、C语言发明了一种不是很完美的解决方案,是三种链接属性的方法。思路:将明显不会在其他C文件中引用(只在当前C文件中引用)的函数/全局变量,使用static修饰使其成为内链接属性,这样在链接时即使2个C文件中有重名的函数/全局变量,只要其中一个或2个为内链接属性就没事。(在一定程度上解决,没有根本解决问题)

static的第二种用法:修饰全局变量和函数

1、普通的函数/全局变量,默认链接属性是外部的。
2、static修饰的函数/全局变量,链接属性是内部链接。


结束语

本文章介绍到这里。结合本文章介绍的,从C语言变量的这四大属性入手了解程序中每一个变量,相信大家都有巨大的收获。以及可以解释相关的疑问,如:“一个函数内的局部变量为什么在函数外不能使用?” “局部变量为什么分配在栈上?或者说局部变量为什么是临时生命周期?”等等。这四大属性相互之间是独立的,对大家理解代码可能没有太大的作用,但是将它们相互关联起来威力可是巨大的。接下来出一个文章将结合本章的内容了解下存储类关键字的精彩“人生”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux——虚拟机安装Linux系统

实验1-2 虚拟机安装Linux系统 VMware 9.0 虚拟机Linux镜像ISO文件相关工具可以在这里边找到 http://pan.baidu.com/s/1ntA18FJ 或者请自行下载使用 创建新的虚拟机,如下图: 下一步:选择安装配置类型为“典型”如下图: 下一步&…

k8s之Ingress

Ingress和Ingress控制器介绍 Ingress官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/ Ingress控制器官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/ 在k8s中将一个…

Multipartfile判断文件类型的简单处理办法。

通过浏览器上传的文件在后台需要验证文件类型。如果单纯匹配后缀名的方式是有风险的,容易被换了后缀的病毒文件给破坏掉。 比如: 如果我上传已修改的文件。(把xlsx改成了jpg) 这样,无法识别出来真实的内容。 所以为了…

java基础巩固-宇宙第一AiYWM:为了维持生计,架构知识+分布式微服务+高并发高可用高性能知识序幕就此拉开(六:Hystrix之熔断、降级、限流)~整起

Hystrix 中文文档:https://www.apiref.com/spring-cloud-zh/dalston/#_circuit_breaker_hystrix_clients服务雪崩:服务 A 调用了服务 B,服务 B 再调用了服务 C,但是因为某些原因,服务 C 顶不住了,这个时候大…

Strimzi Kafka Bridge(桥接)实战之三:自制sdk(golang版本)

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是《Strimzi Kafka Bridge(桥接)实战》的第三篇,前文咱们掌握了Strimzi Kafka Bridge的基本功能:基于http提供各种kafk…

特海国际通过港交所上市聆讯:翻台率下滑明显,张勇夫妇为实控人

撰稿|汤汤 来源|贝多财经 近日,海底捞(HK:06862)海外业务分拆公司特海国际控股有限公司(下称“特海国际”)通过港交所上市聆讯。据贝多财经了解,特海国际将以介绍形式于港交所主板上市。所谓介绍形式&…

数据挖掘Java——Apriori算法的实现

一、Apriori算法的前置知识 Apriori算法是一种挖掘关联规则的频繁项集算法,其核心思想是通过候选集生成和向下封闭检测两个阶段来挖掘频繁项集。 关联规则挖掘是数据挖掘中最活跃的研究方法之一,最初的动机是针对购物篮分析问题提出的,其目…

[附源码]Node.js计算机毕业设计工会会员管理系统Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

【Linux学习】多线程

目录前言一、初识线程1. 线程的概念2. 线程的优缺点3. 线程异常4. 线程的用途二、Linux中的线程和进程1. 进程和线程的区别2. 进程中的线程共享三、Linux线程控制1. POSIX线程库2. 创建线程3. 线程终止4. 线程等待5. 线程分离四、Linux线程互斥1. 线程互斥的概念2. 互斥量mutex…

蓝桥杯基础算法(一)—— 快速排序

文章目录1. 基本思想2. 图解过程3. 代码模板4. 例题讲解🍑 快速排序🍑 第 k 个数1. 基本思想 快速排序是 Hoare 于 1962年 提出的一种二叉树结构的交换排序方法。 其基本思想为: (1)确定分界点:在数组中…

从零开始的MySQL(1)

目录1.MySQL的安装2.MySQL的基本操作2.1 展示数据库2.2 创建数据库2.3 选中数据库2.4 删除数据库2.5 常用数据类型2.5.1 整形2.5.2 浮点数2.6 创建表2.7 查看表2.7 查看表结构2.8 删除表3.数据库增删改查3.1 单行插入3.2 多行插入3.3 插入日期3.4 select查询3.4.1 select3.4.2 …

Jprofiler监控服务器的cpu

现象&#xff1a;压测过程中&#xff0c;发现应用服务器的cpu使用率比较高>80%&#xff0c;我们就可以判断服务器的cpu使用率太高了。 一般cpu太高有两种情况&#xff0c; 1.接口的性能非常好&#xff0c;比如响应时间<10ms&#xff0c;tps很高&#xff0c;此时的cpu使用…

CSDN官方插件猿如意可以用ChatGPT啦!

什么是 ChatGPT Chat GPT 是一种由 AI 技术驱动的自然语言处理工具&#xff0c;可让您与聊天机器人进行类似人类的对话等它是基于OpenAI的GPT-3架构进行构建的&#xff0c;并经过训练&#xff0c;以便能够回答人类的问题并进行自然对话ChatGPT可以回答关于各种话题的问题&#…

基于SSM广州旅游攻略网站的设计与实现

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;

【Unity】摄像机跟随鼠标移动以物体为中心旋转 物体根据视线方向移动

描述 实现摄像机根据鼠标移动跟随物体旋转&#xff0c;以摄像机前物体为中心&#xff0c;摄像机围绕物体旋转&#xff0c;并使摄像机时刻指向物体 实现效果 Unity 组件设置 Camera 组件设置 Body 组件设置 实现代码 CameraRotateMove.cs 摄像机跟随和旋转 using System.Co…

神经网络常用的训练方式,什么是神经网络训练法

1、神经网络中的模型训练是什么意思? 无导师学习网络 神经网络中的模型训练是通过自动寻找样本中的内在规律和本质属性,自组织、自适应地改变网络参数与结构。 神经网络在系统辨识、模式识别、智能控制等领域有着广泛而吸引人的前景&#xff0c;特别在智能控制中&#xff0c;…

寄存器内存读写指令(二) —— 多寄存器读写 LDM / STM

有的时候&#xff0c;CPU可能会遇到 a; b; c&#xff0c;这个时候为了提升效率&#xff0c;CPU可能会一次将多个寄存器里的变量保存到内存中。这个时候之前介绍的 LDR / STR 指令虽然也能实现&#xff0c;但只能操作一个寄存器的读写。 因此&#xff0c;考虑到这点&#xff0c…

基于FPGA的PWM发生器设计

目录 引言 设计说明 设计特点 设计思路 设计源码 整数除法模块

超级好看的 Edge 浏览器新标签页插件:好用、好看、免费浏览器必备

BdTab 新标签页 BdTab新标签页扩展是一款免费无广告、简单好用的的高颜值新标签页扩展。 BdTab它颜值高、简单好用、支持高度自定义&#xff1a; 在登录之后支持云备份&#xff0c;支持快速切换搜索引擎&#xff0c;支持快速查看浏览历史记录和书签&#xff0c;用起来非常方便…

数据结构与算法——Java实现排序算法(一)

目录 一、排序算法 1.1 排序算法基本介绍 1.2 衡量程序执行的方法 1.2.1 事后统计法 1.2.2 事前估算的方法 二、 时间复杂度 2.1 时间频度 2.2 时间复杂度 2.2.1 常见的时间复杂度 2.2.2 常数阶O(1) 2.2.3 对数阶O(log2底n) 2.2.4 线性阶O(n) 2.2.5 线性对数阶O(n…