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开发,数据…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
