C语言:函数
C语言:函数
- 函数的概念
- 库函数
- 自定义函数
- 实参与形参
- return语句
- 数组做参数
- 声明与定义
- extern
- static
- 嵌套调用
函数的概念
在C语言中,存在一个函数的概念,有人也将其翻译为子程序。
在数学中,函数是一个完成特定功能的公式,比如传入x的值,就能输出满足函数的y值。C语言函数也同理,C语言的函数是一个完成某项特定任务的代码段。
而我们常见的函数,分为库函数与自定义函数,接下来我一一为大家介绍。
库函数
C语言标准中,规定了一系列常用的函数标准,称为标准库。编译器厂商就会根据这个标准来实现一系列函数,供用户使用,这些函数就称之为库函数。
要注意,库函数不是C语言官方实现的,C语言只制定标准,具体实现是编译器的厂商来完成的,所以不同的编译器下,库函数的实现可能不同,但是用法是一致的。
库函数是在标准库对应的头文件中声明的,所以库函数的使用需要包含对应的头文件。
自定义函数
顾名思义,自定义函数就是用户可以自己设计函数。
语法:
返回类型 函数名(参数)
{//代码
}
返回类型:就是函数结束时返回什么样类型的值,比如我们调用rand函数,其会返回一个整数给我们,那么rand函数的返回类型就是int。
参数:就是用户使用这个函数,需要传入的值。
比如这样一个加法函数:
int add(int x, int y)
{int z = x + y;return z;
}
函数名就是add
,而add
左侧的int
就是函数的返回类型,说明add
函数最后会返回一个int
类型的数据。
(int x, int y)
就是函数的参数,这说明使用这个函数需要传入两个int
类型的数据。
在需要使用函数时,可以这样:
add(3, 5);
也就是函数名(参数)
的形式。
实参与形参
含函数使用的过程中,我们把参数分为形参和实参。
实参:
在以上的add
函数中,我们在调用时add(3, 5)
中的3
和5
就是实参,它们是传入函数的数据。
形参:
在定义函数时,add
函数名后面的(int x, int y)
中的x和y就是形参。
为什么叫做形参呢?实际上,如果只是定义了add
函数而不去调用的话,x
和y
只是形式上存在的,它们并不会向内存申请空间,不会真实存在,所以叫做形参。
而形参是实参的一份临时拷贝,对形参的改动不会影响实参。
比如下面的函数:
void func(int x)
{x++;
}int main()
{int a = 0;func(a);printf("%d", a);return 0;
}
上述函数中,a
就是一个实参,起初a = 0
,当我们把a
传给函数func
,形参x
得到a
的值。在函数内部对形参进行了x++
,此时x = 1
,当函数结束时,输出a的值。
最后输出的a = 0
,因为x
作为形参,x++
对a
没有影响。
return语句
当我们的函数需要返回值的时候,就需要return语句,return后面接着的值,就是函数最后返回给外界的值。
- return后面可以是数值,也可以是表达式。
- return后面也可以什么都没有,直接写return;,这种形式适合返回值为void类型。
- return后面的值类型如果与返回类型不一致,编译器则会将其隐式转化。
- 如果函数中有分支语句,要保证每种情况都有返回值。
数组做参数
数组也可以做函数的参数,比如这样:
void func(int arr[])
{
}
其中int arr[]
就是一个数组类型的参数,其可以接收一个数组。
数组传参时,直接传入数组名即可:
int main()
{int arr[5] = {1, 2, 3, 4, 5};func(arr);return 0;
}
- 当一维数组做形参时,数组的长度是可以省略的。
- 当二位数组做形参时,行可以省略,列不可以省略。
- 当数组做参数,实参和形参是同一个数组,修改形参会对实参造成影响。
声明与定义
C语言的函数声明和定义是定义函数的两个主要部分。
函数定义是指在函数声明的基础上,给出函数的具体实现。函数定义包含函数的返回值类型、函数名、函数的参数列表和函数体。函数定义的目的是为了给出函数的具体实现,也就是函数体中要执行的代码。
函数定义的语法格式如下:
返回类型 函数名(参数)
{// 函数体
}
也就是我们先前讲的基本格式,我们实现函数的功能,就是在函数定义时完成的。
函数声明是指在函数被调用之前,在代码的某个地方提前声明函数的存在。函数声明告诉编译器函数的名称、函数参数的类型和返回值类型。函数声明的目的是为了让编译器在编译过程中能够正确地解析函数的调用。
函数声明的语法格式如下:
返回值类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...)
比如:
int sum(int a, int b);
这就是一个函数的声明,可以理解为函数声明就是函数定义去掉了{}内部的内容。
不过函数声明也可以只有类型,没有形参名称,比如这样:
int sum(int, int);
函数声明和定义的关系是:函数声明是对函数定义的提前声明,函数定义是对函数的具体实现。在实际使用中,通常将函数的声明放在头文件中,将函数的定义放在源文件中。这样做的好处是可以将函数的声明和定义进行分离,方便代码的管理和维护。
需要注意的是,在C语言中,函数的声明和定义可以放在任意顺序,只要在函数被调用之前可以访问到函数的声明即可。
extern
在C语言中,extern
关键字用于声明一个全局变量或者函数,但不进行定义。它可以被用于多个源文件中,用于告诉编译器该变量或函数是在其他源文件中定义的。
在C语言中,变量的声明和定义是不同的。声明告知编译器该变量的类型和名称,而定义则为该变量分配存储空间并初始化它。如果在一个源文件中声明一个全局变量,那么在其他源文件中访问该全局变量就需要使用extern
关键字。
这里是一个例子来说明extern
关键字的使用:
假设我们有两个源文件:main.c和helpers.c。我们希望在main.c中使用helpers.c中定义的全局变量count
和函数increment()
。
首先,我们在helpers.c中定义全局变量:
int count = 0;void increment() {count++;
}
然后,在main.c中声明这些全局变量和函数,并使用extern
关键字告诉编译器它们是在其他源文件中定义的:
#include <stdio.h>extern int count; // 声明count变量
extern void increment(); //声明increment函数int main() {increment(); // 调用increment函数printf("count: %d\n", count); // 访问count变量return 0;
}
注意,在main.c中,我们需要包含helpers.c中定义的函数的头文件,以便在编译过程中编译器可以知道函数的签名。
编译并运行这些代码,输出将会是count: 1
。这是因为我们在increment函数中增加了count变量的值,并在main函数中访问了它。
总结一下,extern
关键字是用于在一个源文件中访问另一个源文件中定义的全局变量和函数。它将变量或函数的声明与定义分离,使得代码更加模块化和可扩展。
static
在C语言中,"static"是一个关键字,用于修饰变量和函数。它的行为和作用会根据修饰的对象不同而有所不同。下面分别介绍"static"关键字在变量和函数中的作用,并给出相关案例。
-
"static"修饰变量:
-
在函数内部,"static"修饰的局部变量会被赋予静态的存储持续时间。这意味着变量的生命周期将持续到程序结束,而不是在函数执行完后销毁。此外,静态局部变量的作用域仍然是局部的,只能在定义它的函数内部使用。
-
例子:
#include <stdio.h>void example() {static int count = 0;count++;printf("Count: %d\n", count); }int main() {for (int i = 0; i < 5; i++) {example();}return 0; }
输出结果:
Count: 1 Count: 2 Count: 3 Count: 4 Count: 5
在上面的例子中,静态变量"count"被定义为函数"example()"的局部变量。每次调用"example()"函数时,"count"值递增并打印。由于静态变量的存储持续时间为整个程序,因此每次调用"example()"函数时,"count"的值会保留。
-
在全局范围内,"static"修饰的全局变量具有内部链接,即只能在当前源文件中访问,其他源文件中不可见。
-
例子:
// File1.c static int global_var = 10;// File2.c #include <stdio.h>extern int global_var;int main() {printf("Global Variable: %d\n", global_var);return 0; }
输出结果:
Global Variable: 10
在上面的例子中,我们在File1.c中声明了一个静态全局变量"global_var"。由于它是静态的,所以只能在同一源文件中访问。然后,在File2.c中通过extern关键字声明"global_var",确保在其他源文件中可见,从而在main函数中进行访问。
-
-
"static"修饰函数:
- 在函数声明前,"static"修饰的函数具有内部链接。这意味着该函数只能在当前源文件中访问,其他源文件中不可见。
- 例子:
输出结果:// File1.c static void static_function() {printf("This is a static function.\n"); }// File2.c extern void static_function();int main() {static_function();return 0; }
在上面的例子中,我们在File1.c中定义了一个静态函数"static_function()“。由于它是静态的,所以只能在同一源文件中访问。然后,在File2.c中通过extern关键字声明"static_function()”,确保在其他源文件中可见,从而在main函数中进行访问。This is a static function.
总结:
- 在C语言中,"static"关键字的作用取决于其修饰的对象。它可以用于修饰局部变量和全局变量,以及函数声明。
- 对于局部变量,"static"赋予了它们静态存储持续时间和保留其值的能力。
- 对于全局变量,"static"给予了它们内部链接特性,使其只能在同一源文件中访问。
- 对于函数声明,"static"使其具有内部链接特性,使其只能在同一源文件中访问。
嵌套调用
在C语言中,函数的嵌套调用指的是在一个函数中调用另一个函数,而被调用的函数又可以继续调用其他函数。这种嵌套调用的方式可以实现代码的模块化,提高代码的可读性和可维护性。
下面以一个简单的例子来说明函数的嵌套调用:
#include <stdio.h>int func2(int num)
{printf("In func2\n");return num * num;
}int func1(int num)
{printf("In func1\n");int result = func2(num);return result + 1;
}int main()
{int number = 3;int result = func1(number);printf("Result: %d\n", result);return 0;
}
在上面的例子中,有三个函数:main
、func1
和func2
。main
函数是程序的入口,func1
和func2
是被调用的函数。
main
函数中定义了一个整型变量number
,并将其赋值为3。然后调用func1
函数,将number
作为参数传递给func1
。在func1
函数中,可以看到它调用了func2
函数,并将num
作为参数传递给func2
。func2
函数执行完毕后,返回结果给func1
,最后func1
将其结果加1并返回给main
函数。
运行上述代码,输出结果如下:
In func1
In func2
Result: 10
从结果可以看出,main
函数调用func1
函数,func1
函数又调用了func2
函数,实现了函数的嵌套调用。通过函数的嵌套调用,可以将代码按照功能划分为若干个小模块,提高代码的可读性和可维护性。
相关文章:
C语言:函数
C语言:函数 函数的概念库函数自定义函数实参与形参return语句数组做参数声明与定义externstatic 嵌套调用 函数的概念 在C语言中,存在一个函数的概念,有人也将其翻译为子程序。 在数学中,函数是一个完成特定功能的公式࿰…...

jmeter-问题一:关于线程组,线程数,用户数详解
文章目录 jmeter参数介绍1.线程数2.准备时长(Ramp-up)3.循环次数4.same user on each iteratio5.调度器 场景一:当你的线程组中线程数为1,循环为1场景二:当你的线程组中线程数为2,循环为1场景三:当你的线程组中线程数为1ÿ…...
golang 通过 cgo 调用 C++ 库
思路 将 C 库包装成 C 库 -> golang 通过 cgo 调用 C 库 C 相关文件 目录列表 include/ some.h C 库头文件some_wrapper.h < 用于将 C 库包装成 C 库的头文件 lib/ libsome.a C 库 src/ some_wrapper.cpp < 用于将 C 库包装成 C 库的源码文件 源码示例 some.h…...

使用 IDEA 开发一个简单易用的 SDK
目录 一、什么是 SDK 二、为什么要开发 SDK 三、开发 SDK 的详细步骤 四、导入 SDK 进行测试 附:ConfigurationProperties 注解的介绍及使用 一、什么是 SDK 1. 定义:软件开发工具包 Software Development Kit 2. 用于开发特定软件或应用程序的工…...
CSS transition(过渡效果)详解
CSS过渡效果(Transition)是一种在CSS3中引入的动画效果,它允许开发者在元素状态变化时(如鼠标悬停、类更改等)平滑地改变CSS属性值,从而创建出平滑的动画效果。过渡效果可以应用于多种CSS属性,如…...

Android13多媒体框架概览
Android13多媒体框架概览 Android 多媒体框架 Android 多媒体框架旨在为 Java 服务提供可靠的接口。它是一个系统,包括多媒体应用程序、框架、OpenCore 引擎、音频/视频/输入的硬件设备,输出设备以及一些核心动态库,比如 libmedia、libmedi…...

一文读懂:MybatisPlus从入门到进阶
快速入门 简介 在项目开发中,Mybatis已经为我们简化了代码编写。 但是我们仍需要编写很多单表CURD语句,MybatisPlus可以进一步简化Mybatis。 MybatisPlus官方文档:https://www.baomidou.com/,感谢苞米豆和黑马程序员。 Mybat…...

C语言--------指针(1)
0.指针&指针变量 32位平台,指针变量是4个字节(32bit/84)--------x86 64位平台,指针变量是8个字节(64bit/88)--------x64 编号指针地址;我们平常讲的p是指针就是说p是一个指针变量; ************只要…...
Vite 下一代的前端工具链,前端开发与构建工具
一、Vite 简介 官方中文网站:Vite | 下一代的前端工具链 官方定义: Vite,下一代的前端工具链,为开发提供极速响应。 Vue3.4版本,Vue新版本使用Vite构建、开发、调试、编译。 Vite的优势 极速的服务启动 使用原生…...

【SpringBoot】FreeMarker视图渲染
目录 一、FreeMarker 简介 1.1 什么是FreeMarker? 1.2 Freemarker模板组成部分 1.3 为什么要使用FreeMarker 二、Springboot集成FreeMarker 2.1 配置 2.2 数据类型 2.2.1 字符串 2.2.2 数值 2.2.3 布尔值 2.2.4 日期 2.3 常见指令 2.3.2 assign 2.3…...

巴尔加瓦算法图解:算法运用。
树 如果能将用户名插入到数组的正确位置就好了,这样就无需在插入后再排序。为此,有人设计了一种名为二叉查找树(binary search tree)的数据结构。 每个node的children 都不大于两个。对于其中的每个节点,左子节点的值都比它小,…...

Docker的镜像和容器的区别
1 Docker镜像 假设Linux内核是第0层,那么无论怎么运行Docker,它都是运行于内核层之上的。这个Docker镜像,是一个只读的镜像,位于第1层,它不能被修改或不能保存状态。 一个Docker镜像可以构建于另一个Docker镜像之上&…...

忘记 RAG:拥抱Agent设计,让 ChatGPT 更智能更贴近实际
RAG(检索增强生成)设计模式通常用于开发特定数据领域的基于实际情况的ChatGPT。 然而,重点主要是改进检索工具的效率,如嵌入式搜索、混合搜索和微调嵌入,而不是智能搜索。 这篇文章介绍了一种新的方法,灵感…...

利用路由懒加载和CDN分发策略,对Vue项目进行性能优化
目录 一、Vue项目 二、路由懒加载 三、CDN分发策略 四、如何对Vue项目进行性能优化 一、Vue项目 Vue是一种用于构建用户界面的JavaScript框架,它是一种渐进式框架,可以用于构建单页应用(SPA)和多页应用。Vue具有简单易学、灵…...

【Scala】1. 变量和数据类型
1. 变量和数据类型 1.1 for begining —— hello world 新建hello.scala文件,注意object名字与文件名一致。 object hello { def main(args:Array[String]): Unit { println("hello world!") } }运行后打印结果如下: hello world!Pr…...

何时以及如何选择制动电阻
制动电阻的选择是优化变频器应用的关键因素 制动电阻器在变频器中是如何工作的? 制动电阻器在 VFD 应用中的工作原理是将电机减速到驱动器设定的精确速度。它们对于电机的快速减速特别有用。制动电阻还可以将任何多余的能量馈入 VFD,以提升直流母线上的…...

消息中间件:Puslar、Kafka、RabbigMQ、ActiveMQ
消息队列 消息队列:它主要用来暂存生产者生产的消息,供后续其他消费者来消费。 它的功能主要有两个: 暂存(存储)队列(有序:先进先出 从目前互联网应用中使用消息队列的场景来看,…...

Rust开发WASM,浏览器运行WASM
首先需要安装wasm-pack cargo install wasm-pack 使用cargo创建工程 cargo new --lib mywasm 编辑Cargo.toml文件,修改lib的类型为cdylib,并且添加依赖wasm-bindgen [package] name "mywasm" version "0.1.0" edition "…...

Vue3编写简单的App组件(二)
一、Vue3页面渲染基本流程 1、入口文件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><link rel"icon" href"/favicon.ico"><meta name"viewport" content"widthde…...

java Servlet 云平台教学系统myeclipse定制开发SQLServer数据库网页模式java编程jdbc
一、源码特点 JSP 云平台教学系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助 系统采用serlvet dao bean,系统具有完整的源代码和数据库 ,系统主要采用B/S模式开发。开发 环境为TOMCAT7.0,Myeclipse8.5开发,数据…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...