C语言作用域与内存布局

news2024/11/27 8:25:46

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起探讨和分享Linux C/C++/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。


C语言作用域与内存布局

    • 作用域
        • 1. 局部变量
        • 2. 静态局部变量
        • 3. 全局变量
        • 4. 静态全局变量
        • 5. extern声明全局变量
        • 6. 全局函数和静态函数
    • 内存布局
        • 1. 内存分区
        • 2. 存储类型
        • 3. 内存操作函数


专栏:《精通C语言》


作用域

C语言变量的作用域分为:

  • 代码块作用域(代码块是大括号{}之间的一段代码)
  • 函数作用域
  • 文件作用域

1. 局部变量

局部变量也叫auto自动变量(auto关键字可以省略不写),一般情况下代码块{}内部定义的变量都是局部变量,它有如下特点:

  • 在一个函数内定义,只在函数范围内有效
  • 在复合语句中定义,只在复合语句中有效
  • 随着函数调用的结束或复合语句的结束,即作用域的结束,局部变量的生命周期也结束
  • 如果没有给局部变量赋初值,那么随机变量的值为随机值
#include <stdio.h>

void test()
{
	//auto只能出现在{}内部
	auto int b = 10; //相当于  int b = 10; //auto可省略
}

int main(void)
{
	//b = 100; //error, 在main作用域中没有b, b的生命周期在test()内部

	if (1)
	{
		//在复合语句中定义,只在复合语句中有效
		int a = 10;
		printf("a = %d\n", a);
	}

	//a = 10; //error离开if()的复合语句,a生命周期结束
	
	return 0;
}

2. 静态局部变量

static修饰的局部变量称为静态局部变量

  • static局部变量的作用域也是在定义的函数内有效
  • static局部变量的生命周期和程序运行周期一样,同时staitc局部变量的值只初始化一次,但可以赋值多次(记忆功能)
  • static局部变量若未赋以初值,则由系统自动赋值,数值型变量自动赋初值0,字符型变量赋空字符
#include <stdio.h>

void fun1()
{
	int i = 0;
	i++;
	printf("i = %d\n", i);
}

void fun2()
{
	//静态局部变量,没有赋值,系统赋值为0,而且只会初始化一次
	static int a;
	a++;
	printf("a = %d\n", a);
}

int main(void)
{
	fun1();
	fun1();
	fun2();
	fun2();
	
	return 0;
}

3. 全局变量

  • 在函数外定义,可被本文件及其它文件中的函数所使用,如果其它文件中的函数想要调用此变量,必须通过extern声明为外部定义
  • 全局变量的生命周期和程序运行周期一样
  • 不同文件的全局变量不可重名

4. 静态全局变量

static修饰的全局变量称为静态全局变量

  • 在函数外定义,作用域被限制在所定义的文件中
  • 不同文件静态全局变量可以重名,但作用域不冲突
  • static全局变量的生命周期和程序运行周期一样,同时staitc全局变量的值只初始化一次

5. extern声明全局变量

通过extern声明一个变量,表示这个变量在别的文件中已经定义了,这里只是声明,而不是定义。

6. 全局函数和静态函数

在C语言中函数默认都是全局的,使用关键字static可以将函数声明为静态,函数被声明为static静态函数就意味着这个函数只能在定义这个函数的文件中使用,在其他文件中不能调用,即使在其他文件中声明这个函数都没用。对于不同文件中的staitc函数名字可以相同。

注意:

  • 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰。
  • 同一源文件中,允许全局变量和局部变量同名,在局部变量的作用域内,全局变量不起作用。
  • 所有的函数默认都是全局的,意味着所有的函数都不能重名,但如果是staitc函数,那么作用域是文件级的,所以不同的文件static函数名是可以相同的。

内存布局

1. 内存分区

C源代码经过预处理、编译、汇编、链接4步后生成一个可执行程序。
在 Linux 下,程序是一个普通的具有可执行权限的文件,以下列出一个二进制可执行文件的基本情况:
在这里插入图片描述

通过上图可以得知,在没有运行程序前,也就是说程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、数据区(data)和未初始化数据区(bss)3 个部分(有时候也可以把data和bss合起来叫做静态区或全局区)。

  • 代码区:存放 CPU 执行的机器指令。通常代码区是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令。另外,代码区还规划了局部变量的相关信息。

  • 全局初始化数据区/静态数据区(data段):该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)。

  • 未初始化数据区(又叫 bss 区):存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被内核初始化为 0 或者空(NULL)。

程序在加载到内存前,代码区和全局区(data和bss)的大小就是固定的,程序运行期间不能改变。然后,运行可执行程序,系统把程序加载到内存,除了根据可执行程序的信息分出代码区(text)、数据区(data)和未初始化数据区(bss)之外,还额外增加了栈区、堆区。
在这里插入图片描述

  • 代码区(text segment)
    加载的是可执行文件代码段,所有的可执行代码都加载到代码区,这块内存是不可以在运行期间修改的。

  • 未初始化数据区(BSS)
    加载的是可执行文件BSS段,位置可以分开亦可以紧靠数据段,存储于数据段的数据(全局未初始化,静态未初始化数据)的生存周期为整个程序运行过程。

  • 全局初始化数据区/静态数据区(data segment)
    加载的是可执行文件数据段,存储于数据段(全局初始化,静态初始化数据,文字常量(只读))的数据的生存周期为整个程序运行过程。

  • 栈区(stack)
    栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。

  • 堆区(heap)
    堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

2. 存储类型

类型作用域生命周期存储位置
auto变量代码块{}内当前函数栈区
static局部变量代码块{}内整个程序运行期初始化在data段,未初始化在BSS段
extern变量整个程序整个程序运行期初始化在data段,未初始化在BSS段
static全局变量当前文件整个程序运行期初始化在data段,未初始化在BSS段
extern函数整个程序整个程序运行期代码区
static函数当前文件整个程序运行期代码区
register变量代码块{}内当前函数运行时存储在CPU寄存器
字符串常量当前文件整个程序运行期data段

3. 内存操作函数

  • memset

#include <string.h>
void *memset(void *s, int c, size_t n);
功能:将s的内存区域的前n个字节以参数c填入
参数:
s:需要操作内存s的首地址
c:填充的字符,c虽然参数为int,但必须是unsigned char , 范围为0~255
n:指定需要设置的大小
返回值:s的首地址

  • memcpy/memmove

#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
功能:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上。
参数:
dest:目的内存首地址
src: 源内存首地址,注意, dest和src所指的内存空间不可重叠
n: 需要拷贝的字节数
返回值:dest的首地址
memmove()功能用法和memcpy()一样,区别在于dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。

  • memcmp

#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n);
功能:比较s1和s2所指向内存区域的前n个字节
参数:
s1:内存首地址1
s2:内存首地址2
n:需比较的前n个字节
返回值:
相等:=0
大于:>0
小于:<0


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


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

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

相关文章

[附源码]Python计算机毕业设计SSM基于RationalRose的教务管理系统开发(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

css flex布局 —— 项目属性 align-self

align-self属性定义 flex 子项单独在侧轴&#xff08;纵轴&#xff09;方向上的对齐方式&#xff0c;可覆盖 align-items 属性。 默认值为 auto&#xff0c;表示继承父元素的 align-items 属性&#xff0c;如果没有父元素&#xff0c;则等同于 stretch。 语法 .item {align-…

Web3中文|跑路的NFT项目Frosties,是如何被“绳之以法”?

本文&#xff0c;我们将深入探讨传说中的NFT项目Frosties跑路过程&#xff0c;以及该项目的创始人在私吞超100 万美元后是如何被抓获的。 Frosties NFT跑路过程 Frosties是一个由8888幅作品组成的NFT系列&#xff0c;具有Doodles的轻松、有趣的风格。该系列于2022年1月9日上线…

Talk预告 | 阿里巴巴达摩院算法工程师许贤哲:DAMO-YOLO:兼顾速度与精度的高效目标检测框架

本期为TechBeat人工智能社区第463期线上Talk&#xff01; 北京时间12月15日(周四)20:00&#xff0c;阿里巴巴达摩院算法工程师——许贤哲的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “DAMO-YOLO&#xff1a;兼顾速度与精度的高效目标检测框架”…

mysql索引的使用详解

一、 普通索引 ALTER TABLE 表名 ADD INDEX index_store_id索引名 ( 字段名 ) 二、唯一索引 它与前面的"普通索引"类似&#xff0c;不同的就是&#xff1a;索引列的值必须唯一&#xff0c;但允许有空值。 ALTER TABLE table_name ADD UNIQUE (column)三、 组合索引…

实用干货| 教你一键实现微信小程序转APP

自有APP不但有利于企业品牌推广&#xff0c;同时还更有利于收集用户相关数据&#xff0c;从而帮助企业及时调整发展方向和目标。而从0到1进行自有APP的开发其实是一项耗时耗力的工程&#xff0c;为了节约时间和成本&#xff0c;不少企业考虑直接将其现有微信小程序转换成商用AP…

21--Django-后端开发-Web开发模式、API接口以及Restful规范

一、Web开发模式 前后端混合开发模式 前后端分离 二、API接口 1.定义: 通过网络,规定了前后台信息交互规则的url链接,是前后台信息交互的媒介。 2.特点: 1)url:长得像返回数据的url链接 https://api.map.baidu.com/place/v2/search 2)请求方式:get、post、put、patc…

大一学生《Web前端网课作业》基于HTML+CSS自我介绍网页设计与制作

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

Usaco Trainning刷怪旅第一层第三题:Friday the Thirteenth

Usaco Training网站 关注我持续更新usaco training题目 Is Friday the 13th really an unusual event? That is, does the 13th of the month land on a Friday less often than on any other day of the week? To answer this question, write a program that will compute …

构造哈夫曼树以及求哈夫曼编码、树的带权路径长度

我们先搞清楚这几个概念 构造哈夫曼树的方法 将每种字符出现的频率先收集起来放在最上方&#xff0c;然后选择两个频率最小的增加到图中&#xff0c;并将他们的和作为他们的父节点&#xff0c;增加到图中&#xff0c;在最上方删除选择的两个节点&#xff08;4和2&#xff09;&a…

尚硅谷的项目---尚医通 前端模块 vue-element-admin

我的node版本是16的版本&#xff0c;一开始我使用的老师提供的压缩包 一直出现错误 无法 npm install 其实后来发现是node版本过高的原因&#xff0c;小伙伴们可以讲版本调到跟老师的版本一样 我是嫌麻烦&#xff0c;我就直接从github上下载了一个新的版本 网站是&#xff1…

java中的反射和Class类

动态语言 VS 静态语言&#xff1a; 动态语言是一类在运行时可以改变其结构的语言&#xff0c;例如&#xff1a;新的函数对象甚至代码可以被引进&#xff0c;已有的函数可以被删除或是其他结构上的变化&#xff0c;通俗点说就是在运行时&#xff0c;代码可以根据某些条件改变自…

【AI with ML】第 4 章 :使用公共数据集和TensorFlow 数据集

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Web前端105天-day43-JSCORE

JSCORE03 目录 前言 一、复习 二、块级作用域 三、声明提升 四、模板字符串 五、箭头函数 六、箭头函数的this 七、数组高阶函数 7.1.every 7.2.some 7.3.filter 7.4.map 7.5.join 八、ajax 九、作业 总结 前言 JSCORE学习开始 一、复习 函数的触发方式 call: 临…

跑步用头戴式耳机好吗、五款最适合跑步用的耳机推荐

无论您是为即将举行的运动进行训练的经验丰富的运动员&#xff0c;还是喜欢慢跑的人&#xff0c;一副好的运动型耳机都可以让您的日常锻炼变得与众不同。我们测试过市面上220多种蓝牙耳机&#xff0c;以下是我们针对跑步和锻炼的最佳耳机选择建议&#xff1a; 1、南卡Runner P…

[附源码]Nodejs计算机毕业设计基于web的学生社团管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

springboot 创建第一个项目

创建springboot项目的方式有很多&#xff0c;一般通过IDEA直接创建。 参考&#xff1a;创建SpringBoot项目的四种方式 - Linqylin - 博客园 代码结构&#xff1a; 代码示例&#xff1a; 创建项目的时候导入了web依赖。 pom.xml&#xff1a; <?xml version"1.0&qu…

Marvell交换机芯片SMI接口读写协议

Marvell的88E6XXX系列交换机芯片基本都提供SMI&#xff08;Serial Management Interface&#xff09;接口。 SMI接口使用2线串行通信&#xff0c;一个MDC提供时钟&#xff0c;一个MDIO为双向数据引脚。 外部CPU通过这2个引脚访问芯片内部的寄存器。 SMI接口的通信时序如图所示&…

【Python】Gamma分布详解

文章目录初步介绍形状特征初步介绍 在学习Gamma分布之前&#xff0c;有必要复习一下Poisson分布&#xff1a;泊松分布 Poisson分布指的是&#xff0c;单个事件在某一刻发生的概率。Gamma分布更进一步&#xff0c;指的是某个事件在某个时刻发生第nnn次的概率。 p(x)xk−1e−λ…

PowerDesigner 模型类型介绍

目录 PowerDesigner 提供了两种方式组织模型 分别是Categories和Model types 1.Categories方式是从企业架构建模角度出发&#xff0c;主要包含业务层&#xff0c;信息层&#xff0c;应用层&#xff0c;技术层&#xff0c;需求与规划层 1.1 业务层主要用于业务流程&#xff0c…