首页 > 其他分享 >于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)

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

时间:2025-01-19 18:03:57浏览次数:3  
标签:return 函数 int 源文件 变幻 static 灵动 浪漫 声明

在这里插入图片描述

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

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

这里写目录标题

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

1.1 单个文件

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

#include<stdio.h>
int pan_duan_run_nian(int x)
{
	if ((x % 4 == 0) && (x % 100 != 0) || (x % 400 == 0))
		return 1;
	else
		return 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;
	else
		return 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;
	else
		return 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;
   else
   	return 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 修饰。

三、结尾

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

标签:return,函数,int,源文件,变幻,static,灵动,浪漫,声明
From: https://blog.csdn.net/2501_90089451/article/details/145169410

相关文章

  • 计算机毕业设计Springboot“飞卷”窗帘报价管理系统的设计与实现 基于Springboot的“
    计算机毕业设计Springboot“飞卷”窗帘报价管理系统的设计与实现q62s9t2z(配套有源码程序mysql数据库论文)本套源码可以先看具体功能演示视频领取,文末有联xi可分享随着窗帘行业的不断发展,市场竞争日益激烈,传统的窗帘报价方式已难以满足现代企业对效率和准确性的要求。为了......
  • 《浪漫沙加2:七英雄的复仇》游戏启动时报错提示“找不到facesdk.dll”文件的原因和处理
    对于众多游戏爱好者而言,《浪漫沙加2:七英雄的复仇》无疑是一款备受期待、渴望沉浸其中的佳作。然而,不少玩家在满心欢喜准备启动游戏时,却遭遇了令人沮丧的报错提示——“找不到facesdk.dll”文件,这一状况瞬间打破了游戏的美好憧憬,探寻背后原因与处理方案势在必行。报错提示......
  • 请用canvas写一个关于520浪漫表白的代码
    当然可以,以下是一个使用HTML5<canvas>元素创建520浪漫表白信息的简单示例。此代码会在canvas上绘制一个心形,并在心形内部写上"520我爱你"。<!DOCTYPEhtml><html><head><title>520浪漫表白</title><style>body{display:flex;......
  • 主打一个“小巧灵动”:Vite + Svelte
    作者:来自vivo互联网大前端团队- WeiXing在研发小型项目时,传统的Vue、React显得太“笨重”。本文主要针对开发小型项目的场景,谈谈Vite+Svelte是如何让项目变得“小巧灵动”,并横向对比Svelte和Vue的性能表现,对二者的加载流程做详细分析。一、背景为了统一技术标准......
  • 苹果灵动岛功能怎么玩
    苹果灵动岛功能怎么玩?苹果的灵动岛功能是一种新的交互方式,可以显示各种提示信息,包括来电显示、信息、后台使用的APP(如音乐)等。以下是一些关于如何玩转灵动岛功能的建议:查看和管理通知:灵动岛会显示通知和警报,你可以点击灵动岛直接切换到关联的应用程序6。互动游戏:有一些互动游戏可......
  • 【2025最新】用python代码浪漫教程!——新年祝福信息
    文章目录一、2025年跨年祝福信息Python脚本示例:二、代码说明导入模块:主程序:三、注意事项一、2025年跨年祝福信息当然,我可以为你提供一个简单的Python代码示例,用于在2025年跨年时执行一些特定的任务,比如打印新年祝福信息。Python脚本示例:importdatetimeimport......
  • springboot毕设双月灵动体育馆管理系统论文+程序+部署
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着社会的发展和人们健康意识的提高,体育活动的参与度不断上升,体育馆作为体育活动的重要场所,其管理面临着诸多挑战。传统的体育馆管理模式多为静......
  • 浪漫的表白代码
    <!DOCTYPEhtml><html><head><metacharset="utf-8"/><title></title><style>html,body{width:100%;height:100%;padding:0;margin:0;background:#00......
  • C++天使的灵动心跳代码:类和对象(中下)
    文章目录4.拷贝构造函数4.1默认拷贝构造函数4.2显式调用拷贝构造函数5.运算符重载函数5.1赋值运算符重载函数5.1.1默认赋值运算符重载函数5.1.2显式调用赋值运算符重载函数5.2const取地址运算符重载函数希望读者们多多三连支持小编会继续更新你们的鼓励就是我......
  • C++天使的灵动心跳代码:类和对象(中上)
    文章目录1.类的六大默认成员函数2.构造函数2.1默认构造函数2.2显式调用构造函数3.析构函数3.1默认析构函数3.2显式调用析构函数希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力!本篇将介绍类和对象中的重点部分,六大函数中的前四个尤为重要,所以......