当前位置: 首页 > news >正文

C语言(8) 函数

第五章 函数

一段功能代码,被称为函数

1. 为了避免代码的重复。 复用性。 开发不用从头开始(库函数)。
2. 模块化的思想 。 大问题,分解成小问题,逐个解决。
设计函数 ,高内聚,低耦合。 功能越单一越好 ,对外部依赖越少越好。
函数在使用前,需要先定义(告诉编译器有这个功能),再使用。 定义时包含(声明)

函数的定义

函数返回值 函数名(参数类表)
{
函数体;
return x;
}
参数列表 (数据类型 形式参数1,数据类型 形式参数2,数据类型 形式参数3...)
函数返回值 数据类型 ,函数在调用完毕后,一般情况都是有结果值。 这个值就有数据的类型 。 如果函数
的返回值 设计为void ,那么函数调用(使用)后,没有结果,也就没有数据

1. 如果设计函数的时候,没有给定函数返回值的 ,默认是int 。如果确实没有什么需要返回的,可以是
void 。
2. 如果函数的执行流程,运行到,return 是返回到,函数的调用处。 return后的代码,将不会被执
行。
3. 参数在传递的过程中,需要保证,参数的个数一致,类型 匹配(类型一致或可以隐式类型转换

//函数的定义,实现具体
int add()
{
int a =20;
int b =10;
int ret = a+b;
return ret; // 返回结果,返回函数调用的地方。
}
int main()
{
int result = add(); // 函数的使用,() 表示调用函数, int result = ret; int
result =30;
printf("result is %d\n",result);
return 0;
}

函数的调用

void fun1()
{}
void fun2(int arg1,int arg2) 形参,形式参数
{}
函数后面的圆括号,不可以省略。
函数名(); // fun1();
int a=0, int b=20 ;
// 参数个数一致, 数据类型也一致。
函数名(arg1,arg2); // fun2(a,b); 实参,实际参数

//函数的定义 ,实现具体
int add()
{
int a =20;
int b =10;
int ret = a+b;
return ret; // 返回结果,返回函数调用的地方。
}
int main()
{
int result = add(); // 函数的使用,() 表示调用函数, int result = ret; int
result =30;
printf("result is %d\n",result);
return 0;
}
主调函数,在这个示例中,main 是主调函数。调用功能的发起者。
被调函数 ,在main中使用add的功能,add 就是被动调用的函数。

函数的声明

在实际代码编写过程。没有办法保证, 函数的定义,一定在函数的调用前出现 (多文件编程)。编译器在编译的过程中,就会出现未登记函数,就会警告。为了避免这种情况, 就要对函数进行声明

int add(int a,int b); //声明
int main()
{
....
add(1+2,4*5); // 函数的调用,但是函数的定义在后面定义的,这时 会出现警告。
....

}
int add(int a,int b)
{
return a+b;
}
int add(int a,int b) ,函数的原型,函数头。 包含,函数名,参数列表(参数的个数,每个参数的数据类型) ,返回值的数据类型。

变量的作用域和生命周期

作用域:

变量定义后,可以被访问的区域。

局部作用域: 局部变量

变量作用域在离定义该变量最近的大括号内。当发生函数调用后,作用域发生了变化,在被调函数内部,在主调函数内部定义的变量,都不能使用。

#include <stdio.h>
int add()
{
return a+b; // 不能访问到主调的 a,b 变量 。
}
int main()
{
int a = 10; //局部作用域
int b =20;//局部作用域
int c = add();
return 0;
}

全局作用域: 全局变量

在所有的源文件( 同一个工程中 所有.c) , 在任意位置都可以直接使用的区域。
变量的定义,放在所有函数的外面。 就是全局变量

int a = 10; // 全局变量, 整个工程中,任意位置都可以被访问。
int b =20;
int add()
{
return a+b;
}
int main()
{
int c = add();
printf("c is %d\n",c);
return 0;
}

生命周期

定义:

变量从开辟内存空间开始 到 变量的内存空间的回收 结束 ,的这个时间段,被称为生命周期。

局部变量的生命周期

1. 函数内部定义的变量
2. 函数的参数
3. 函数内部定义的变量,一定要给初值。如果没有给,就是随机值

在定义开始的地方,申请内存。 执行到函数结束,空间回收。

全局变量的生命周期

1.在所有函数之外定义的变量。
2. 可以给初值。如果不给初值 ,由系统负责初始化为0 ;

全局变量,在a.out 正式运行起来前,就要把空间开辟好,在程序结束后,空间释放 。全局变量有全局生命周期。

  • 在同一个作用域中,标识符(变量名,数组名,函数名) ,不能同名。
  • 如果一个作用域大,一个作用域小,出现同名标识符。 出现隐藏。

变量的隐藏

int a = 10;
int b =20;
int add()
{
return a+b;
}
int main()
{
int a =1;
int b =3;
int c = add();
int d = a+b; // 这个地方使用的是,局部变量。全局变量被隐藏。
printf("c is %d\n",c);

return 0;
}

变量的存储类型

存储类型 数据类型 变量名;
1. auto int a; 用的相对少
2. register int b; 用的相对少
3.extern int c;
4.static int d;

1. auto,

自动存储类型 。 局部变量。 这个关键字 ,可以省略 。定义变量时,内存空间自动开辟,离开作用域时自动释放。内存的栈区(stack)。 函数内部定义的变量,函数的参数。

2. register

寄存器 . 建议编译器把某个变量存储在cpu的寄存器中。

register int c;

3. extern

外部变量。 声明。 导出,目的是为了让其他的源文件,可以使用

1.c
#include <stdio.h>
extern int a; // 声明,表示有这个变量,在其他的.c 中
extern int b;
extern void fun();
int main()
{
int c = a+b;
printf("a+b %d\n",c);
fun();
}
2.c
int a =10;// 定义,开辟内存空间
int b =20;
void fun()
{
}
gcc 1.c 2.c

4.static 静态的

可以修饰变量,或函数。 用static 修改的变量,内存的数据区

static 修改局部变量
如果局部变量前加 static ,变量的生命周期是整个程序运行的周期,但作用域不变。

第一运行fun函数时, i, 分配空间+初始化。 如果不是第一次运行,这个变量 ,就不会在分配空间,和初始化。相当于 static int i = 0,这段没有 了。


int fun()
{
static int i = 0 ;// 全局生命周期
i++;
return i;
}
int main()
{
int num = 0;
printf("input num");
scanf("%d",&num);
int j = 0 ;
int count = 0 ;
for(j=0;j<num;j++)
{
count = fun();
}
// i = 20; //errror ,不能访问i。 i本身是存在,但是没在i的作用域范围内
printf("count is %d\n",count);
return 0;
}

static 修饰全局变量

表示 这个变量只能在本模块(本源文件中 依然全局变量)中使用。其他的源文件 不可以使用。 static 的作用 限制作用域。

static 修饰函数

static 的作用 限制作用域。 避免函数重名

5. a.out 运行起来后的内存分布图

http://www.jsqmd.com/news/808026/

相关文章:

  • Java基础全套教程
  • 2026 年成都防水补漏正规靠谱公司推荐:选择成都防水公司的三大“硬指标”深度解析“友易家防水”与“华亿雨鸿”的工程实力与避坑指南 - 资讯焦点
  • 别再硬编码DLL路径了!Qt QLibrary跨平台动态库加载的5个最佳实践(附代码避坑)
  • ClaudeCode 高效使用技巧2:添加skill
  • Python自动化AutoCAD终极指南:用pyautocad库实现高效CAD开发
  • 从臃肿到精悍:利用虚拟环境优化PyInstaller打包体验
  • 【Excel提效 No.075】一句话搞定注释批量提取导出
  • VMware macOS虚拟机解锁实用指南:Unlocker 3.0深度解析与完整教程
  • 关于在Jupyter Notebook中巧妙规避ipykernel_launcher.py: error: argument的实战解析
  • 谷歌云详细教程 – 带你系统性学习Google Cloud
  • 别让直觉带路:Infoseek视角下的噪音过滤与火情预警实战
  • 办公增效工具!OpenClaw 中文版本一键安装教学
  • 告别答辩PPT焦虑:用百考通AI高效打造专业学术报告
  • 别再傻傻分不清了!3D打印/建模中STL的ASCII和二进制格式,到底该选哪个?
  • 争分夺秒与步步为营:Infoseek舆情系统如何重构危机响应的时间哲学
  • AzurLaneLive2DExtract:快速提取碧蓝航线Live2D模型的完整指南
  • 014、LVGL坐标系统与对齐方式
  • vllm启动Qwen/Qwen3.6-35B-A3B踩坑日记
  • CRM 系统是什么?一文读懂客户关系管理系统的核心价值与应用
  • PCL2启动器游戏启动失败:终极解决方案与完整指南
  • Photo Sphere Viewer、Three.js、Pannellum怎么选?2024年Web全景图库横向评测与入门指南
  • PowerToys Awake:让Windows电脑在你需要时保持清醒的3种智能模式
  • 如何做变量操作化:从抽象概念到测量指标
  • TVA与传统视觉技术的本质区别——以工业视觉检测为例(11)
  • 跨摄像机不是识别接力,而是空间连续:镜像视界空间智能跟踪中枢
  • 低代码革命:Gemini3.1Pro赋能全民开发
  • 9大网盘直链解析工具LinkSwift:本地化文件下载解决方案
  • 从手动到自动:基于Test Sequence与Test Manager的Simulink模型高效测试流程构建
  • Unpivot逆透视:列名转列值的利器与海量数据下的性能陷阱
  • iOS 音频硬件架构:采样率、位深、声道、音频缓冲区核心解析