【C语言从不挂科到高绩点】16-作用域和自定义头文件

news2024/11/24 5:33:45

 Hello!彦祖们,俺又回来了!!!,继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中的函数:

本套课程将会从0基础讲解C语言核心技术,适合人群:

  1. 大学中开设了C语言课程的同学
  2. 想要专升本或者考研的同学
  3. 想要考计算机等级证书的同学
  4. 想要从事C/C++/嵌入式开发的同学

================点个关注吧================

=========================================

7.7 变量的作用域

全局变量:定义在所有函数之外,全局变量在程序退出之前都有效。

局部变量:定义在函数内部(形式参数也属于局部变量),局部变量在函数退出的时候会被释放。

7.7.1 局部变量

局部变量的概念:凡是被一对花括号{}包裹的变量都称为局部变量。for 循环中定义的 i 是局部变量,在 main 函数中定义的变量也属于局部变量。

局部变量的特点:

  1. 某个函数内部的局部变量,存储在该函数的栈空间。
  2. 函数定义局部变量仅在函数中使用,在函数外部无法使用
  3. 在函数退出的时候会被回收资源,由于函数内存取消,存在其空间里面的局部变量也会被释放。局部变量也称为临时变量
  4. 函数的形式参数也属于局部变量。
  5. return 之后不可再访问函数的局部变量,因此返回局部变量的地址是错误的

栈内存的特点:

  1. 每个函数被调用的时候,系统会自动分配一块内存给函数。用于存储局部变量。
  2. 每个函数退出的时候,系统会自动回收函数的栈内存。
  3. 系统为函数分配内存,遵循从上往下分配的原则。

7.7.2 全局变量

  1. 程序中全局变量存在于所有函数之外,包括 main 函数。
  2. 全局变量的作用域是整个文件,随着程序结束而释放。
  3. 全局变量和局部变量可以同名,当同名时,优先使用局部变量。

7.7.3 演示案例

#include <stdio.h>


// 全局变量:定义在所有函数之外的变量
int number = 100;// 全局变量
// 全局变量的作用域:整个文件,在程序结束之前,所有的函数中都可以使用


void swaps(int a,int b){ // a,b 形式参数,属于局部变量,只能在swaps函数中使用
	int temp =a; // temp是在函数内部定义的变量,也属于局部变量
	a = b;
	b = temp;

	int number = 400;// 当局部变量和全局变量重名时,会使用局部变量
	printf("swap函数-number:%d\n",number); 

}

void test(){
	// temp是在swaps函数中定义的局部变量,只能在swaps函数局部使用
	// swaps函数结束后会被回收 ,所以在其他函数中不能使用temp局部变量
	//printf("temp:%d\n",temp);
	printf("test函数-number:%d\n",number);// 全局变量
}

int main()
{
	swaps(20,30);
	test();
	printf("main函数-number:%d\n",number); // 全局变量

	return 0;
}

7.7.4 static 关键字

如果对于局部变量进行 static 修饰,那么该变量在定义的时候将会被分配内存(不需要等到函数被调用的时候分配内存)。直到程序结束之后才会被释放。这个 static 修饰静态局部变量只会初始化 1 次

#include <stdio.h>


/**
如果对于局部变量进行 static 修饰,
那么该变量在定义的时候将会被分配内存(不需要等到函数被调用的时候分配内存)。直到程序结束之后才会被释放。
这个 static 修饰静态局部变量只会初始化 1 次。
**/
void show(){
	// 局部变量:每次调用函数的时候,都会重新定义并且初始化
	int num = 200; 
	num++;

	printf("%d-普通的局部变量\n",num );
} // 出了这个大括号,num会被回收释放掉


void show1(){
	// 被static修改的局部变量:静态局部变量
	// 1. static修饰的局部变量只会初始化一次
	// 2. static修饰的局部变量只有在程序结束的时候才会被回收,
	//    不会因为函数结束被回收掉
	static int num = 200;// 无论调用多少次函数,这个代码只执行一次,只会初始化1次
	// 在后续调用中,不会再重新初始化,会直接用前面的值
	num++;

	printf("%d-普通的局部变量\n",num );
}

int main()
{
	show(); //201
	show(); // 201

	show1(); // 当这个函数结束时,static修饰的num不会被回收
	show1(); // 所以这几个show1() 共用的是同一个num变量
	show1();
	show1();

	return 0;
}

7.7.5 extern 关键字

extern 关键字可以做外部全局变量的声明,表示使用的是外部文件中的全局变量。

1. 新建一个 extern1.c 源文件

#include <stdio.h>

int number = 100;


void show(){

	printf("extern1.c 文件中的show函数:%d\n",number );
}

2. 新建一个 extern2.c 源文件

#include <stdio.h>

int number = 100;


void show(){

	printf("extern1.c 文件中的show函数:%d\n",number );
}

3. 联合编译:将两个源文件编译成一个可执行文件

gcc extern1.c extern2.c -o  main
  1. 编译之后,会出现如下问题:

修改 extern2.c 中的代码



#include <stdio.h>

// 注意:此处不是在定义变量,表示在引用其他文件中的number变量
extern int number; // 不做初始化

extern void show();// 表示此处引用的是外部文件的show()函数

int main(){
	show();
	printf("extern2.c文件中的main函数:%d\n",number); //100
	return 0;
}

运行后效果:

实际开发中一个项目通常会分为不同源文件进行开发,每个源文件负责的功能不同。通常在一个源文件中引用另一个源文件中的全局变量。这个时候可以使用 extern 关键字来引用外部的全局变量。

extern int number;

当 cpu 看到了 extern 关键字,就会认为这个变量是引用的外部文件中的变量,此时就不会重新定义变量。

7.7.6 extern 注意事项

在一个项目的多个文件中,不能存在两个变量名相同的全局变量或者相同名字的函数,否则就会出错。

extern 可以解决:当一个文件中需要使用某个变量,但是这个变量已经在其他文件中定义过了,此时不能在当前文件再定义了。这个时候就可以使用 extern 关键字,去引用其他文件的变量。

使用 extern 引用外部文件全局变量时,不能赋值,一旦赋值,编译器会认为是在重新定义变量,而不是引用其他文件的变量。

例如:下面代码中给 number 赋值为 30

#include <stdio.h>

// 注意:此处不是在定义变量,表示在引用其他文件中的number变量
extern int number =30; // 不做初始化

extern void show();// 表示此处引用的是外部文件的show()函数

// int num = 30;

int main(){
	show();
	printf("extern2.c文件中的main函数:%d\n",number); //100
	return 0;
}

在编译的时候就会出现问题:

如果声明引用外部全局变量,但是如果找不到外部全局变量时,就会出错

例如:将 extern1.c 中定义 number 代码注释掉

#include <stdio.h>

// int number = 400;
int num = 20;

void show(){

	// printf("extern1.c 文件中的show函数:%d\n",number );
}

编译时,会出现找不到引用的错误:

如果全局变量不想给外部其他文件使用,可以在全局变量前面加 static

例如:在 extern1.c 定义 number 之前加一个 static

#include <stdio.h>

static int number = 400;
int num = 20;

void show(){

	printf("extern1.c 文件中的show函数:%d\n",number );
}

编译之后:

特别注意!!:在一个项目的多个文件中,不能存在名字相同的多个全局变量和函数,否则编译的时候就会报multiple definition of ‘XXX’错误

7.8 自定义头文件

7.8.1 include 的用法

#include 叫做文件包含指令,用来引入对应的头文件(.h 文件)

#include 是 C 语言中预处理命令的一种,处理过程很简单,就是将头文件中的内容插入到该命令所在的位置。从而将头文件和当前源文件链接成一个源文件(实际上就是复制粘贴)

#include 的两种用法

#include <stdio.h>
#include "myhead.h"
  • 使用尖括号<>, 编译器会到系统路径下查找头文件
  • 使用 双引号“”,编译器首先会在当前项目目录查找头文件,如果没有找到再到系统路径下查找。
  • 一般建议:引入 C 语言标准库中的头文件使用<>,引用自定义头文件使用双引号“”

7.8.2 引入自定义头文件

新建一个源文件 my.c,添加函数

// 函数定义
int sum(int m,int n){
	return m+n;
}

新建一个头文件 my.h(头文件的后缀名.h),里面添加函数的声明

int sum(int m,int n);

新建一个源文件,添加程序的入口


#include <stdio.h>

// 引入自己写的头文件my.h
#include "my.h"

// 引入头文件,实际上就是将头文件中的内容复制粘贴到此处位置上
// 所以,引入头文件“my.h”等价于在此处写了如下代码
// int sum(int m,int n);

int main(){

	printf("%d\n",sum(1,4));

	return 0;
}

联合编译:编译的时候,只编译.c 源文件,.h 头文件可以 不参与编译

需要注意的是:联合编译实际上就是将所有源文件中的内容编译到同一个执行程序文件中,所以会发现虽然我们在 main.c 中没有定义 sum 函数,但是可以直接使用 my.c 中的 sum 函数。导入 my.h 头文件,只是将函数声明的代码复制到了 main.c 中。

7.8.3 注意事项

一般建议不要在头文件中编写函数的定义和变量的定义。头文件中一般只包含宏定义、结构体声明、函数声明、以及带有 extern 的全局变量的引用

原因在于:

  1. 一个项目中不能同时存在多个名字相同的全局变量以及函数。
  2. 引入头文件,实际上相当于将头文件中的内容复制粘贴到源文件中。
  3. 如果说这个项目中多个源文件中同时引入了包含全局变量定义或者函数定义的头文件,就会出现multiple definition of ‘XXX’的错误

例如:如果在 my.h 中定义了变量或者函数.



int number = 10;

int sum(int m,int n);

void swap(int a,int b){
	int temp = a;
	a = b;
	b = temp;
}

此时如果只在 main.c 中引入 my.h 头文件,代码是可以正常运行的。

但是如果在 my.c 中也引入了 my.h 头文件,那么编译的时候,就会出现问题

#include "my.h"

// int number=10;
// int sum(int m,int n);

// 函数定义
int sum(int m,int n){
	return m+n;
}

错误信息如下:会显示 number 和 swap 重复定义了

所以,不要在头文件中定义变量和函数!!!!

 ---------------------------------------------------------------------- 

​分享不易,耗时耗力,喜欢的同学给个关注和赞吧

承接毕设指导,技术答疑,学习路上想要找私人教练的同学可以私信我

更多学习资料,公众号:墨轩学习网,B站:墨轩大楼

----------------------------------------------------------------------

另有下图需求的也记得私信我哟,专业班子


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

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

相关文章

LLM 大模型研习:当下热门 AI 大模型的生成原理与逻辑

前言 在过去数年里&#xff0c;人工智能领域迎来了前所未有的变革&#xff0c;其中大规模预训练模型的崛起尤为引人注目。像GPT系列、BERT、T5、DALLE和CLIP等模型&#xff0c;凭借强大的语言理解与生成能力&#xff0c;在自然语言处理&#xff08;NLP&#xff09;、计算机视觉…

Android Auto助力电动汽车智能驾驶

随着技术的飞速发展&#xff0c;电动汽车&#xff08;EVs&#xff09;成为未来出行的重要趋势。然而&#xff0c;EVs 的普及不仅仅代表环保选择&#xff0c;它们还推动了智能汽车技术的发展。Android Auto 的集成无疑为电动汽车用户带来了更便捷和智能的驾驶体验。 一、智能互联…

解决Matlab报错:MEX 文件 ‘D:\MATLAB\toolbox\maple\maplemex.mexw64‘ 无效: 缺少依赖共享库

安装Maple之后&#xff0c;再使用MATLAB就报了以上错误。 按照以下解决方法可以正常运行&#xff1a; 1. 在添加路径下删除D:\matlab\toolbox\Maple 2. 再添加路径 D:\matlab\toolbox\symbolic 3. 保存

UDS 诊断 - InputOutputControlByIdentifier(按标识符的输入输出控制)(0x2F)服务

UDS 诊断服务系列文章目录 诊断和通信管理功能单元 UDS 诊断 - DiagnosticSessionControl&#xff08;诊断会话控制&#xff09;&#xff08;0x10&#xff09;服务 UDS 诊断 - ECUReset&#xff08;ECU重置&#xff09;&#xff08;0x11&#xff09;服务 UDS 诊断 - SecurityA…

8月份美国CPI通胀降至+2.5%

根据劳工统计局&#xff08;BLS&#xff09;最近发布的一份报告&#xff0c;美国CPI&#xff08;消费者价格指数&#xff09;通胀在8月份放缓至2.5%&#xff08;同比&#xff09;&#xff0c;这是自2021年2月以来的最低水平。最新的通胀数据使美国国债收益率和美元指数上升&…

稀土抗菌剂真的能抗菌吗?

在现代生活中&#xff0c;抗菌剂已经成为了我们日常生活的一部分。然而&#xff0c;面对市面上各种抗菌产品&#xff0c;我们如何才能选择既安全又有效的产品呢&#xff1f;近年来&#xff0c;稀土抗菌剂因其独特的抗菌性能而引起了广泛关注。 稀土抗菌剂的抗菌原理 稀土抗菌剂…

基于 SpringBoot 的学习平台

摘 要 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括学习平台的网络应用&#xff0c;在外国学习平台已经是很普遍的方式&#xff0c;不过国内的管理平台可能还处于起步阶段。学习平台具有学习信息管理功能的选择。学习平台…

Jenkins部署若依项目

一、配置环境 机器 jenkins机器 用途&#xff1a;自动化部署前端后端&#xff0c;前后端自动化构建需要配置发送SSH的秘钥和公钥&#xff0c;同时jenkins要有nodejs工具来进行前端打包&#xff0c;maven工具进行后端的打包。 gitlab机器 用途&#xff1a;远程代码仓库拉取和…

OpenHarmony鸿蒙( Beta5.0)智能加湿器开发详解

鸿蒙开发往期必看&#xff1a; 一分钟了解”纯血版&#xff01;鸿蒙HarmonyOS Next应用开发&#xff01; “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…

spring security OAuth2 客户端接入gitee

一、简介 OAuth 是一个开放标准&#xff0c;该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等)&#xff0c;并且在这个过租中无须将用户名和密码提供给第三方应用。通过令牌(token)可以实现这一功能&#xff0c;每一个令牌授权一个特定的…

ATF UFS初始化笔记

1. JESD220 中关于UFS初始化的描述 原文 13.1.3 Initialization and boot code download process The initialization and boot code download process is made up of the following phases: partial initialization, boot transfer and initialization completion. 13.1.3.…

果蔬识别系统性能优化之路(四)

目录 前情提要剩下问题 问题排查解决方案下一步 前情提要 果蔬识别系统性能优化之路&#xff08;三&#xff09; 剩下问题 同步数据库数据并初始化ivf依然要8,9秒 问题排查 通过断点加时间打印&#xff0c;发生其实初始化ivf的时间很快&#xff0c;慢的是数据在网络间的传…

【读论文】End-to-end reproducible AI pipelines in radiology using the cloud

文章目录 End-to-end reproducible AI pipelines in radiology using the cloud01 研究背景与目的医学成像领域&#xff08;1&#xff09;研究现状&#xff08;2&#xff09;存在问题 其他研究领域&#xff1a;基因组学&#xff08;genomics&#xff09;研究目的&#xff1a;提…

Vue3使用vue-qrcode-reader实现扫码绑定设备功能

需求描述 移动端进入网站后&#xff0c;登录网站进入设备管理界面。点击添加设备&#xff0c;可以选择直接添加或者扫一扫。点击扫一扫进行扫描二维码获取设备序列号自动填充到添加设备界面的序列号输入框中。然后点击完成进行设备绑定。 安装vue-qrcode-reader 这里使用的版…

《OpenCV计算机视觉》—— 身份证号码识别案例

文章目录 一、案例实现的整体思路二、代码实现1.首先定义两个函数2.模板图像中数字的定位处理3.身份证号码数字的定位处理4.使用模板匹配&#xff0c;计算匹配得分&#xff0c;找到正确结果 一、案例实现的整体思路 下面是一个数字0~9的模板图片 案例身份证如下&#xff1a; 对…

http有什么方法升级成https?

&#x1f512; 获取与安装证书 JoySSL注册填写申请码230907即可领取免费申请资格https://www.joyssl.com/certificate/select/free.html?nid7 &#x1f4c4; 申请SSL证书 选择证书&#xff1a;首先需选择合适的SSL证书&#xff0c;如域名认证&#xff08;DV&#xff09;、公…

120页ppt丨集团公司战略规划内容、方法、步骤及战略规划案例研究

响应会员需求&#xff0c;晓零分享一份经典资料《120页ppt集团公司战略规划内容、方法、步骤及战略规划案例研究》&#xff0c;欢迎进入星球下载学习。 以下是对企业战略规划三个阶段八个步骤的详细解析&#xff1a; 一、阶段一&#xff1a;内外分析 项目启动和前期准备&…

Parallels Desktop 20 发布下载,macOS Sequoia 和 Windows 11 24H2 支持准备就绪

Parallels Desktop for Mac 20.0.0 (build 55653) - 在 Mac 上运行 Windows macOS Sequoia 和 Windows 11 24H2 支持准备就绪 请访问原文链接&#xff1a;https://sysin.org/blog/parallels-desktop/&#xff0c;查看最新版。原创作品&#xff0c;转载请保出处。 作者主页&a…

Java | Leetcode Java题解之第400题第N位数字

题目&#xff1a; 题解&#xff1a; class Solution {public int findNthDigit(int n) {int d 1, count 9;while (n > (long) d * count) {n - d * count;d;count * 10;}int index n - 1;int start (int) Math.pow(10, d - 1);int num start index / d;int digitInde…

wifiip地址可以随便改吗?wifi的ip地址怎么改变

对于普通用户来说&#xff0c;WiFi IP地址的管理和修改往往显得神秘而复杂。本文旨在深入探讨WiFi IP地址是否可以随意更改&#xff0c;以及如何正确地改变WiFi的IP地址。虎观代理小二将详细解释WiFi IP地址的基本概念、作用以及更改时需要注意的事项&#xff0c;帮助用户更好地…