于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)

在这里插入图片描述

大家好啊,我是小象٩(๑òωó๑)۶
我的博客:Xiao Xiangζั͡ޓއއ

很高兴见到大家,希望能够和大家一起交流学习,共同进步
在这里插入图片描述
这一节我们主要来学习单个函数的声明与定义,static和extern…

这里写目录标题

  • 一、单个函数的声明与定义
    • 1.1 单个文件
    • 1.2 多个文件
  • 二、static和extern
    • 2.1 作用域和生命周期
    • 2.2 static
    • 2.3 static修饰局部变量
    • 2.4 static修饰全局变量(extern声明外部符号)
    • 2.5 static修饰函数
  • 三、结尾

一、单个函数的声明与定义

1.1 单个文件

一般我们在使用函数的时候,直接将函数写出来就使用了。
咱们举之前练习过的一个例子来看,比如写一个函数判断一年是否是闰年。

#include<stdio.h>
int pan_duan_run_nian(int x)
{if ((x % 4 == 0) && (x % 100 != 0) || (x % 400 == 0))return 1;elsereturn 0;
}int main()
{int year = 0;scanf("%d", &year);int a = pan_duan_run_nian(year);if (a == 1){printf("%d为闰年", year);}else{printf("%d不是闰年");}return 0;
}

在这个代码中,这一部分代表的是**函数的定义**:

关于函数的定义:
在C语言中,函数定义是编程中的一个核心概念,它允许你将代码组织成可重用和可维护的模块。函数定义的作用主要包括以下几个方面:
1、代码重用:通过定义函数,你可以避免在多个地方重复编写相同的代码。当你需要在程序中多次执行某个任务时,只需调用定义好的函数即可,从而提高了代码的重用性。
2、模块化编程函数将程序划分为多个逻辑模块,每个模块负责完成特定的任务。这种结构化的编程方式使得程序更易于理解和维护。
3、提高可读性将复杂的程序逻辑分解为多个函数,每个函数都有明确的目的,这可以提高代码的可读性。阅读和理解一个由多个简单函数组成的程序,比阅读一个包含大量复杂逻辑的单体程序要容易得多。
4、便于调试: 模块化编程使得在程序出现问题时更容易定位错误。你可以单独测试每个函数,确定哪个函数存在错误,从而减少了调试的复杂性
5、增强代码的可维护性: 当需要修改程序时,只需修改相关的函数,而不需要在整个程序中搜索和修改代码。这大大简化了维护过程,降低了维护成本。
6、促进代码协作:在大型项目中,多个开发人员可以独立地编写和测试各自的函数。通过定义清晰的函数接口,开发人员可以协同工作,确保代码的正确性和一致性。
7、实现递归(后面会学)函数定义允许函数自身调用自身(递归),这是解决某些类型问题(如排序、搜索等)的有效方法

#include<stdio.h>
int pan_duan_run_nian(int x)
{if ((x % 4 == 0) && (x % 100 != 0) || (x % 400 == 0))return 1;elsereturn 0;
}

而这一部分代表着**函数的调用`**:

int a = pan_duan_run_nian(year);

然后,如果我们把函数的定义放在函数调用的后面,像这样:

int main()
{int year = 0;scanf("%d", &year);int a = pan_duan_run_nian(year);if (a == 1){printf("%d为闰年", year);}else{printf("%d不是闰年");}return 0;
}#include<stdio.h>
int pan_duan_run_nian(int x)
{if ((x % 4 == 0) && (x % 100 != 0) || (x % 400 == 0))return 1;elsereturn 0;
}

这个代码在VS2022上编译,会出现下面的警告信息:
在这里插入图片描述
这是因为C语言编译器对源代码进行编译的时候,第一行往下扫描的,当遇到pan_duan_run_nian函数调用的时候,并没有发现前面有pan_duan_run_nian的定义,就报出了上述的警告。
把怎么解决这个问题呢?就是函数调用之前先声明一下pan_duan_run_nian这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数
如:pan_duan_run_nian(int x);这就是函数声明,在C语言中,函数声明(Function Declaration)告诉编译器有关函数的存在、其返回类型、函数名以及参数类型和数量的声明 。函数声明通常位于函数定义之前或在其他文件中,以便编译器在函数调用之前知道函数的签名(即函数的接口)。函数声明中参数只保留类型,省略掉名字也是可以的

函数声明的作用:
1、提前通知编译器:编译器在编译代码时,需要知道函数的签名,以便在函数调用时进行类型检查。函数声明提供了这一信息,使得编译器可以在函数实际定义之前进行编译。
2、避免链接错误:在多个文件的项目中,函数声明允许编译器在编译单独的源文件时知道其他文件中定义的函数的存在。这样,链接器(Linker)可以在链接阶段找到这些函数的实际定义。
3、提高代码可读性:函数声明提供了函数的接口信息,有助于其他程序员理解如何使用该函数。

所以我们给上面的函数加上声明,就会变成下面这样:

pan_duan_run_nian(int x);#include<stdio.h>
int main()
{int year = 0;scanf("%d", &year);int a = pan_duan_run_nian(year);if (a == 1){printf("%d为闰年", year);}else{printf("%d不是闰年");}return 0;
}int pan_duan_run_nian(int x)
{if ((x % 4 == 0) && (x % 100 != 0) || (x % 400 == 0))return 1;elsereturn 0;
}

结果便正常了
在这里插入图片描述
函数的调用一定要满足,先声明后使用
函数的定义也是一种特殊的声明,所以如果函数定义放在调用之前也是可以的。

1.2 多个文件

一般在企业中我们写代码时候,代码可能比较多,不会将所有的代码都放在⼀个文件中;我们往往会根据程序的功能,将代码拆分放在多个文件中,也就是模块化处理。

注意:虽然一个工程会有多个文件,但main函数只能有一个

⼀般情况下,函数的声明、类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)文件中。

我们来举个例子,我们用test.c来调用其它模块代码进行测试,我们用leap.h和leap.c分别来对于函数的声明和函数的定义

像这样:分别创建test.c和leap.c源文件,leap.h头文件
在这里插入图片描述
我们来举一个加法的例子:
我们先来看函数测试的雏形:

#include<stdio.h>
#include"leap.h" //你的头文件是leap.h
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int c = add(a, b);printf("%d", c);return 0;
}

在这里插入图片描述

我们把它放在test.c中
这里我们要注意要把leap.h头文件也包含进去#include"leap.h"

接着,我们看函数的声明:

int add(int x, int y);//函数的声明

在这里插入图片描述
我们把它放在leap.h头文件中

最后是函数的定义:

int add(int x, int y)//函数的定义
{int d = x + y;return d;
}

在这里插入图片描述
我们把它放在leap.c的源文件中

这样我们就写完了,运行看看结果:
在这里插入图片描述
没有问题

二、static和extern

static 和 extern 都是C语言中的关键字。

2.1 作用域和生命周期

**作用域(scope)**是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

  1. 局部变量的作用域是变量所在的局部范围
  2. 全局变量的作用域是整个工程(项目)

生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段

  1. 局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束
  2. 全局变量的生命周期是:整个程序的生命周期(就是程序从开始运行到结束)

2.2 static

在C语言中,static关键字有多种用途,其中之一是用于修饰函数。当static关键字用于函数声明时,它改变了函数的链接属性linkage)。

static函数的特点:
1、内部链接(Internal Linkage)
当一个函数被声明为static时,它的链接属性变为内部链接。这意味着该函数只能在声明它的源文件(.c文件)内部被访问。其他源文件无法直接调用这个函数,即使这些文件包含了该函数的声明。
这有助于封装和隐藏实现细节,防止其他文件直接访问和修改。
2、避免命名冲突
由于static函数只能在其所在的文件内部被访问,因此不同源文件中的同名static函数不会引起命名冲突。
这允许开发者在不同的源文件中使用相同名称的函数,而无需担心命名冲突。
3、生命周期
static关键字对函数的生命周期没有影响。函数的生命周期总是从程序开始执行到程序结束。static关键字仅影响函数的链接属性,即函数的可见性。

static 是 静态的 的意思,可以用来:
• 修饰局部变量
• 修饰全局变量
• 修饰函数

2.3 static修饰局部变量

我们先来看个例子:

#include<stdio.h>
void test()
{int i = 0;i++;printf("%d", i);
}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}

结果是这样的:
在这里插入图片描述
如果我们这样改:

#include<stdio.h>
void test()
{static int i = 0;i++;printf("%d", i);
}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}

结果就会变成这样:
在这里插入图片描述
我们来对比代码1和代码2的效果

代码1的test函数中的局部变量i是每次进入test函数先创建变量(生命周期开始)并赋值为0,然后++,再打印,出函数的时候变量生命周期将要结束(释放内存)

代码2中,我们从输出结果来看,i的值有累加的效果,其实test函数中的i创建好后,出函数的时候是不会销毁的,重新进入函数也就不会重新创建变量,直接上次累积的数值继续计算。

结论:static修饰局部变量改变了变量的生命周期(被static修饰后生命周期会变长),生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被 static 修饰后存储到了静态区。 存储在静态区的变量和全局变量是⼀样的,生命周期就和程序的生命周期⼀样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变的。

使用建议未来一个变量出了函数后,我们还想保留值,等下次进入函数继续使用,就可以使用static修饰

2.4 static修饰全局变量(extern声明外部符号)

extern 是用来声明外部符号的,如果一个全局的符号在A文件中定义的,在B文件中想使用,就可以使用 extern 进行声明,然后使用。

我们首先创建两个源文件,然后我们在其中一个源文件创建一个变量,然后另一个源文件用extern声明一下,像下面的做法一样:

int xiaofeixiang = 666;
#include<stdio.h>
int main()
{extern int xiaofeixiang;//声明一下printf("%d", xiaofeixiang);return 0;}

我们运行看看结果:
在这里插入图片描述
运行一切正常

如果我们这个时候在变量旁边添加static的话:

static int xiaofeixiang = 666;

这个时候我们如果运行的话,就会发现运行错误:

在这里插入图片描述

结论:
static相当于改变作用域一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
本质原因是**全局变量默认是具有外部链接属性的**,在外部的文件中想使用,只要适当的声明就可以使用;但是全局变量被 static 修饰之后,外部链接属性就变成了内部链接属性只能在自己所在的源文件内部使用了,其他源文件,即使声明了,也是无法正常使用的

使用建议:如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰。

2.5 static修饰函数

直接来个例子:

int add(int x, int y)
{return x + y;
}
#include<stdio.h>
extern int add(int x, int y);
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int c = add(a,b);//声明一下printf("%d",c );return 0;}

这里的extern是指声明外部函数的作用
我们运行一下,结果没有问题:
在这里插入图片描述
如果我们在函数前面加上static的话,会发生什么呢,我们来看看:

static int add(int x,int y);

看看结果,直接就报错了:
在这里插入图片描述
其实 static 修饰函数和 static 修饰全局变量是一模一样的,一个函数在整个工程都可以使用,被static修饰后,只能在本文件内部使用,其他文件无法正常的链接使用了
本质是因为 函数默认是具有外部链接属性,具有外部链接属性,使得函数在整个工程中只要适当的声明就可以被使用。但是 被 static 修饰后变成了内部链接属性,使得函数只能在自己所在源文件内部使用

使用建议:一个函数只想在所在的源文件内部使用,不想被其他源文件使用,就可以使用 static 修饰。

三、结尾

这一课的内容就到这里了,下节课继续学习递归的其他一些知识
如果内容有什么问题的话欢迎指正,有什么问题也可以问我!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析】02- A/B 测试:玩转假设检验、t 检验与卡方检验

一、背景&#xff1a;当“审判”成为科学 1.1 虚拟场景——法庭审判 想象这样一个场景&#xff1a;有一天&#xff0c;你在王国里担任“首席审判官”。你面前站着一位嫌疑人&#xff0c;有人指控他说“偷了国王珍贵的金冠”。但究竟是他干的&#xff0c;还是他是被冤枉的&…

HTML应用指南:利用GET请求获取全国特斯拉充电桩位置

随着电动汽车的普及&#xff0c;充电基础设施的建设变得至关重要。作为电动汽车领域的先驱&#xff0c;特斯拉不仅在车辆技术创新上持续领先&#xff0c;还积极构建广泛的充电网络&#xff0c;以支持其不断增长的用户群体。为了提升用户体验和服务质量&#xff0c;开发人员和数…

【原创】大数据治理入门(2)《提升数据质量:质量评估与改进策略》入门必看 高赞实用

提升数据质量&#xff1a;质量评估与改进策略 引言&#xff1a;数据质量的概念 在大数据时代&#xff0c;数据的质量直接影响到数据分析的准确性和可靠性。数据质量是指数据在多大程度上能够满足其预定用途&#xff0c;确保数据的准确性、完整性、一致性和及时性是数据质量的…

OpenVela——专为AIoT领域打造的开源操作系统

目录 一、系统背景与开源 1.1. 起源 1.2. 开源 二、系统特点 2.1. 轻量化 2.2. 标准兼容性 2.3. 安全性 2.4. 高度可扩展性 三、技术支持与功能 3.1. 架构支持 3.2. 异构计算支持 3.3. 全面的连接套件 3.4. 开发者工具 四、应用场景与优势 4.1. 应用场景 4.2. …

寒假1.18

web&#xff08;报错注入&#xff09; [第一章 web入门]SQL注入-2 题解&#xff1a; 打开是个403界面&#xff0c;还以为没开成 通过题目提示&#xff0c;访问/login.php /user.php 合在一起访问屁都没有&#xff0c;分开访问&#xff0c;/login.php回显&#xff1a; /user.p…

如何通过 Apache Airflow 将数据导入 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz 了解如何通过 Apache Airflow 将数据导入 Elasticsearch。 Apache Airflow Apache Airflow 是一个旨在创建、安排&#xff08;schedule&#xff09;和监控工作流的平台。它用于编排 ETL&#xff08;Extract-Transform-Load&#xff0…

企业分类相似度筛选实战:基于规则与向量方法的对比分析

文章目录 企业表相似类别筛选实战项目背景介绍效果展示基于规则的效果基于向量相似的效果 说明相关文章推荐 企业表相似类别筛选实战 项目背景 在当下RAG&#xff08;检索增强生成&#xff09;技术应用不断发展的背景下&#xff0c;掌握文本相似算法不仅能够助力信息检索&…

Jenkins-Pipeline简述

一. 什么是Jenkins pipeline&#xff1a; pipeline在jenkins中是一套插件&#xff0c;主要功能在于&#xff0c;将原本独立运行于单个或者多个节点的任务连接起来&#xff0c;实现单个任务难以完成的复杂发布流程。Pipeline的实现方式是一套Groovy DSL&#xff0c;任何发布流程…

基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多&#xff0c;这里面有高、中、低档&#xff0c;开发方式也不相同。之所以会这样&#xff0c;有价格的因素&am…

C# 修改项目类型 应用程序程序改类库

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

6、原来可以这样理解C语言_函数(1/8)函数的概念

目录 一、函数的概念 一、函数的概念 数学中我们其实就⻅过函数的概念&#xff0c;⽐如&#xff1a;⼀次函数 ykxb &#xff0c;k和b都是常数&#xff0c;给⼀个任意的x&#xff0c;就 得到⼀个y值。 其实在C语⾔也引⼊函数&#xff08;function&#xff09;的概念&#xff0c…

Excel 技巧10 - 如何检查输入重复数据(★★)

本文讲了如何在Excel中通过COUNTIF来检查输入重复数据。 当输入重复数据时&#xff0c;显示错误提示。 1&#xff0c;通过COUNTIF来检查输入重复数据 比如下面是想检查不要输入重复的学号。 选中C列&#xff0c;点 Menu > 数据 > 数据验证 在数据验证页面&#xff0c…

【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)

inode 和 block 的映射 该博文中有详细解释&#xff1a;【Linux系统】inode 和 block 的映射原理 目录与文件名 这里有几个问题&#xff1a; 问题一&#xff1a; 我们访问文件&#xff0c;都是用的文件名&#xff0c;没用过 inode 号啊&#xff1f; 之前总是说可以通过一个…

[计算机网络]一. 计算机网络概论第一部分

作者申明&#xff1a;作者所有文章借助了各个渠道的图片视频以及资料&#xff0c;在此致谢。作者所有文章不用于盈利&#xff0c;只是用于个人学习。 1.0推荐动画 【网络】半小时看懂<计算机网络>_哔哩哔哩_bilibili 1.1计算机网络在信息时代的作用 在当今信息时代&…

Python操作Excel——openpyxl使用笔记(2)

2. 操作工作表 前面提到一个工作簿中会有一个或者多个工作表&#xff0c;当前使用的工作表被称作活动工作表&#xff0c;这里展开介绍一下对于工作表的一些操作。 2.1 枚举所有工作表 使用for循环可以很方便的遍历每个工作表&#xff1a; import openpyxl wb openpyxl.o…

Social LSTM:Human Trajectory Prediction in Crowded Spaces | 文献翻译

概要 行人遵循不同轨迹以避免障碍物和容纳同行者。任何在这种场景中巡航的自动驾驶车辆都需要能够遇见行人的未来位置并相应地调整其路线以避免碰撞。轨迹预测问题能够被看作一个顺序生成任务&#xff0c;其中我们对基于行人过去的位置预测其未来的轨迹感兴趣。根据最近RNN&am…

从零开始:Gitee 仓库创建与 Git 配置指南

引言 Git 是一款广泛使用的版本控制工具&#xff0c;它能够帮助开发者在开发过程中高效地管理代码的版本。而 Gitee&#xff08;码云&#xff09;是国内知名的 Git 托管平台&#xff0c;它提供了强大的代码托管、团队协作和项目管理功能。如果你是 Git 和 Gitee 的新手&#x…

挖掘机检测数据集,准确识别率91.0%,4327张原始图片,支持YOLO,COCO JSON,PASICAL VOC XML等多种格式标注

挖掘机检测数据集&#xff0c;准确识别率91.0%&#xff0c;4327张图片&#xff0c;支持YOLO&#xff0c;COCO JSON&#xff0c;PASICAL VOC XML等多种格式标注 数据集详情 数据集分割 训练组70&#xff05; 3022图片 有效集20&#xff05; 870图片 测试集10&…

CV 图像处理基础笔记大全(超全版哦~)!!!

一、图像的数字化表示 像素 数字图像由众多像素组成&#xff0c;是图像的基本构成单位。在灰度图像中&#xff0c;一个像素用一个数值表示其亮度&#xff0c;通常 8 位存储&#xff0c;取值范围 0 - 255&#xff0c;0 为纯黑&#xff0c;255 为纯白。例如&#xff0c;一幅简单的…

QT 使用QTableView读取数据库数据,表格分页,跳转,导出,过滤功能

文章目录 效果图概述功能点代码分析导航栏表格更新视图表格导出表格过滤 总结 效果图 概述 本案例用于对数据库中的数据进行显示等其他操作。数据库的映射&#xff0c;插入等功能看此博客框架&#xff1a;数据模型使用QSqlTableModel&#xff0c;视图使用QTableView&#xff0…