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

10. C语言 函数详解

本章目录:

    • 前言
    • 1. C 语言函数概述
      • 1.1 函数的定义与结构
      • 1.2 函数声明
      • 1.3 函数调用
    • 2. 函数参数传递
      • 2.1 传值调用
      • 2.2 传引用调用(模拟)
      • 2.3 引用调用(C++ 特性)
    • 3. 内部函数与外部函数
      • 3.1 内部函数
      • 3.2 外部函数
      • 3.3 示例:多个文件中的函数使用
    • 4. 内联函数
      • 4.1 什么是内联函数?
    • 5. 函数的递归调用
      • 5.1 递归的优缺点
    • 6. 总结与最佳实践


前言

在 C 语言中,函数是程序的重要组成部分,它通过将任务划分为多个模块,使得代码更加结构化、可重用、可读性强。本文将从函数的定义、声明、调用、参数传递等多个角度进行详细分析,并结合读者的笔记,提供一些 C 语言函数的最佳实践和应用技巧。


1. C 语言函数概述

1.1 函数的定义与结构

一个 C 程序通常至少包含一个函数——main(),这是程序的入口函数。除了主函数,我们还可以定义其他辅助函数来执行具体任务,函数的定义格式如下:

return_type function_name(parameter_list) {// Function body
}
  • 返回类型:函数返回值的类型。如果函数不返回值,则使用 void
  • 函数名称:函数的标识符。
  • 参数列表:函数接收的输入参数,多个参数之间用逗号分隔。如果没有参数,留空即可。
  • 函数主体:包含具体执行的代码。

1.2 函数声明

函数声明(或称为函数原型)是在调用函数之前告知编译器该函数的返回类型、名称及参数列表。声明的作用是确保函数被正确调用。

return_type function_name(parameter_list);

对于以下函数定义:

int max(int num1, int num2) {if (num1 > num2) {return num1;}return num2;
}

其声明形式为:

int max(int num1, int num2);

1.3 函数调用

当函数被调用时,程序的控制权会转移到被调用的函数。函数执行完毕后,控制权会返回到调用点。调用时,如果函数有参数,需要传入实际参数。如果函数有返回值,可以将返回值存储在变量中。

int result = max(10, 20); // 调用函数

2. 函数参数传递

2.1 传值调用

C 语言默认使用传值调用(Pass by Value)。在传值调用中,函数接收到的是参数的副本,对副本的修改不会影响原始参数。

void swap(int a, int b) {int temp = a;a = b;b = temp;
}int main() {int x = 5, y = 10;swap(x, y);printf("x = %d, y = %d\n", x, y); // 输出 x = 5, y = 10
}

如上所示,尽管函数内交换了 ab 的值,但由于传值调用,xy 的值没有改变。

2.2 传引用调用(模拟)

C 语言没有原生的引用传递,但可以通过指针模拟传引用调用。传递参数的地址,使得函数可以直接修改原始数据。

void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 5, y = 10;swap(&x, &y);printf("x = %d, y = %d\n", x, y); // 输出 x = 10, y = 5
}

2.3 引用调用(C++ 特性)

在 C++ 中,可以使用引用传递(Reference)来直接修改原始变量的值。在 C 语言中,引用传递无法直接实现,但可以通过指针来达到类似的效果。

3. 内部函数与外部函数

在 C 语言中,根据函数能否被其他源文件调用,函数可以分为内部函数外部函数

3.1 内部函数

如果一个函数只在当前源文件内有效,并且无法被其他源文件调用,那么它就是一个内部函数。要将函数定义为内部函数,可以在函数前加上 static 关键字:

static int max(int a, int b) {return (a > b) ? a : b;
}

3.2 外部函数

如果一个函数需要在多个源文件中被调用,通常会定义为外部函数。如果没有使用 static 关键字,C 编译器会默认认为函数是外部函数。如果函数在其他文件中调用,则需要使用 extern 关键字进行声明:

extern int max(int a, int b); // 外部函数声明

3.3 示例:多个文件中的函数使用

假设我们需要在多个文件中调用函数,可以通过 externstatic 实现模块化管理。

file1.c(主文件)

#include <stdio.h>static void delete_string(char str[], char ch);int main() {extern void enter(char str[]); // 外部函数声明extern void print(char str[]); // 外部函数声明char str[100];char c;enter(str);scanf("%c", &c);delete_string(str, c);print(str);return 0;
}static void delete_string(char str[], char ch) {int i, j;for (i = j = 0; str[i] != '\0'; i++) {if (str[i] != ch) {str[j++] = str[i];}}str[j] = '\0';
}

file2.c(输入函数)

#include <stdio.h>void enter(char str[100]) {fgets(str, 100, stdin); // 输入字符串
}

file3.c(输出函数)

#include <stdio.h>void print(char str[]) {printf("%s\n", str);
}

4. 内联函数

4.1 什么是内联函数?

内联函数(inline)是一个特殊的函数,它的定义会被编译器直接嵌入到调用位置,从而避免函数调用的时间开销。内联函数适用于代码量小、调用频繁的场景。

inline void swap(int *a, int *b) {int t = *a;*a = *b;*b = t;
}

内联函数有以下几点需要注意:

  • 递归函数不能定义为内联函数。
  • 函数体应尽量简短,最好只包含简单的操作。

5. 函数的递归调用

递归是一种函数调用自身的技术。虽然递归能够简化代码,但它也可能带来较大的内存消耗和性能问题。下面是一个经典的递归求和的例子:

#include <stdio.h>int sum(int n) {if (n == 1) {return 1;}return n + sum(n - 1); // 递归调用
}int main() {printf("%d\n", sum(4)); // 输出 10return 0;
}

5.1 递归的优缺点

  • 优点:递归能够简化代码的逻辑,使得代码更加简洁。
  • 缺点:递归会消耗更多的内存,特别是递归深度较大的时候,可能导致栈溢出。

6. 总结与最佳实践

  • 函数声明与定义:提前声明函数,确保正确调用。
  • 参数传递:C 默认使用传值调用。传引用可以通过指针实现。
  • 函数重用与模块化:通过函数分割任务,增强代码的可读性与可维护性。
  • 内联函数:适用于频繁调用且代码简单的函数。
  • 递归调用:简化逻辑,但需谨慎使用,避免栈溢出。

C 语言的函数是构建高效、可维护程序的核心工具,通过合理划分任务和传递参数,可以大大提高代码的结构化和可复用性。希望本文能够帮助你更加深入地理解和使用 C 语言中的函数,写出更高效、简洁的代码。


相关文章:

10. C语言 函数详解

本章目录: 前言1. C 语言函数概述1.1 函数的定义与结构1.2 函数声明1.3 函数调用 2. 函数参数传递2.1 传值调用2.2 传引用调用&#xff08;模拟&#xff09;2.3 引用调用&#xff08;C 特性&#xff09; 3. 内部函数与外部函数3.1 内部函数3.2 外部函数3.3 示例&#xff1a;多个…...

NRC优先级中比较特殊的—NRC0x13和NRC0x31

1、基础知识 大家都了解 NRC0x13&#xff0c;表示长度错误和格式错误 NRC0x31&#xff0c;表示DID不支持和数据格式不支持 2、为什么说这两个NRC比较特殊 看下图的标注部分&#xff1a; 2.1、先看NRC0x13 步骤一&#xff1a;仔细看是先判断Minmun Length Check &#xff0…...

ref() 和 reactive() 区别

ref() 和 reactive() 都是 Vue 3 中用于创建响应式数据的方法&#xff0c;但它们之间存在一些关键差异。 首先&#xff0c;ref() 用于创建响应式的标量值&#xff0c;比如数字、字符串、布尔值等基本数据类型&#xff0c;以及对象和数组等复杂数据类型。当你使用 ref() 时&…...

深度学习与计算机视觉 (博士)

文章目录 零、计算机视觉概述一、深度学习相关概念1.学习率η2.batchsize和epoch3.端到端(End-to-End)、序列到序列(Seq-to-Seq)4.消融实验5.学习方式6.监督学习的方式(1)有监督学习(2)强监督学习(3)弱监督学习(4)半监督学习(5)自监督学习(6)无监督学习(7)总结&#xff1a;不同…...

Sprint Boot教程之五十:Spring Boot JpaRepository 示例

Spring Boot JpaRepository 示例 Spring Boot建立在 Spring 之上&#xff0c;包含 Spring 的所有功能。由于其快速的生产就绪环境&#xff0c;使开发人员能够直接专注于逻辑&#xff0c;而不必费力配置和设置&#xff0c;因此如今它正成为开发人员的最爱。Spring Boot 是一个基…...

NaVILA:用于足式机器人导航的VLA模型

论文地址&#xff1a;https://navila-bot.github.io/static/navila_paper.pdf 项目地址&#xff1a;https://navila-bot.github.io/ 本文提出了一种名为NaVILA的机器人导航模型&#xff0c;旨在解决视觉语言导航问题&#xff0c;并允许机器人在更具挑战性和杂乱的场景中进行导…...

大语言模型提示技巧(七)-扩展

扩展是将较短的文本&#xff0c;例如一组提示或主题列表&#xff0c;输入到大型语言模型中&#xff0c;让模型生成更长的文本。我们可以利用这个特性让大语言模型生成基于某个主题的电子邮件或小论文。通过这种方式使用大语言模型&#xff0c;可以为工作与生活提供诸多便利&…...

基类指针指向派生类对象,基类指针的首地址永远指向子类从基类继承的基类首地址

文章目录 基类指针指向派生类对象&#xff0c;基类指针的首地址永远指向子类从基类继承的基类起始地址。代码代码2 基类指针指向派生类对象&#xff0c;基类指针的首地址永远指向子类从基类继承的基类起始地址。 代码 #include <iostream> using namespace std;class b…...

25年01月HarmonyOS应用基础认证最新题库

判断题 “一次开发&#xff0c;多端部署”指的是一个工程&#xff0c;一次开发上架&#xff0c;多端按需部署。为了实现这一目的&#xff0c;HarmonyOS提供了多端开发环境&#xff0c;多端开发能力以及多端分发机制。 答案&#xff1a;正确 《鸿蒙生态应用开发白皮书》全面阐释…...

wps宏js接入AI功能和接入翻译功能

wps的js越来越强大了&#xff0c;很实用的功能&#xff0c;爱了 表格wps js接入AI 表格wps js接入翻译功能&#xff0c;自定义翻译语言和目标语言...

【Logstash03】企业级日志分析系统ELK之Logstash 过滤 Filter 插件

Logstash 过滤 Filter 插件 数据从源传输到存储库的过程中&#xff0c;Logstash 过滤器能够解析各个事件&#xff0c;识别已命名的字段以构建结构&#xff0c; 并将它们转换成通用格式&#xff0c;以便进行更强大的分析和实现商业价值。 Logstash 能够动态地转换和解析数据&a…...

深度学习:Java DL4J基于RNN构建智能停车管理模型

### 深度学习&#xff1a;Java DL4J基于RNN构建智能停车管理模型 #### 引言 随着城市化进程的加速&#xff0c;停车问题日益成为城市管理的难点和痛点。传统的停车场管理方式效率低下&#xff0c;导致停车场资源无法得到充分利用&#xff0c;车主停车体验差。为了解决这些痛点…...

花生好坏缺陷识别数据集,7262张图片,支持yolo,coco json,pasical voc xml格式的标注,识别准确率在95.7%

花生好坏缺陷识别数据集,7262张图片&#xff0c;支持yolo&#xff0c;coco json&#xff0c;pasical voc xml格式的标注&#xff0c;识别准确率在95.7% 数据集分割 训练组87&#xff05; 6353图片 有效集8% 606图片 测试集4% 303图片 预处理 自动定…...

2025年:AI化浪潮中的社会变迁与商业革新

随着人工智能(AI)技术的迅猛发展,2025年将成为一个转折点。这一年,AI不仅将深入到日常生活和商业运营的各个角落,还将引发一系列深刻的社会、经济和技术变革。以下是对未来一年可能出现的“AI化”现象的预测与展望。 AI进入主流文化的标志 超级碗广告:在2025年的超级碗上…...

filebeat、kafka

elk的架构 es数据库&#xff1a;非关系型数据库&#xff0c;json格式 logstash&#xff1a;收集日志 kibana&#xff1a;图形化的工具 ↓ 以上三种结合起来即为日志收集系统 filebeat 作用&#xff1a;filebeat是一款轻量级的日志收集工具&#xff0c;不依赖java环境&…...

js单例模式

保证一个类只有一个实例,并提供一个访问它的全局访问点 实现 静态方法实现 class SingleTon{//全局的访问点static getInstance(){// 保证一个类只有一个实例if(!this.instance){this.instancenew SingleTon()}return this.instance}}let aSingleTon.getInstance()let bSing…...

【设计模式】装饰器与代理模式的对比

文章目录 装饰器模式&#xff08;Decorator Pattern&#xff09;代理模式&#xff08;Proxy Pattern&#xff09;两者之间的区别 装饰器模式&#xff08;Decorator Pattern&#xff09; 装饰器模式是一种结构型设计模式&#xff0c;它允许你动态地将责任附加到对象上&#xff…...

Proteus-8086调试汇编格式的一点心得

这阵子开始做汇编的微机实验&#xff08;微机原理与接口技术题解及实验指导&#xff0c;吴宁版本13章&#xff09;&#xff0c;中间出了挺多问题&#xff0c;解决后记录下。 先上电路图 用子电路来仿真发现仿真的时候子电路这块根本没有高低电平输出&#xff0c;只好把子电路拿…...

什么是Kafka?有什么主要用途?

大家好&#xff0c;我是锋哥。今天分享关于【什么是Kafka&#xff1f;有什么主要用途&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是Kafka&#xff1f;有什么主要用途&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka 是一个分布式流…...

SpringBoot插件

SpringBoot的插件机制是其强大灵活性的重要体现&#xff0c;它允许开发人员将应用程序的不同功能模块打包为独立的插件&#xff0c;并可以动态地加载和卸载这些插件。以下是对SpringBoot插件机制的详细解析&#xff1a; 一、插件机制的概念 插件机制是一种软件开发方法&#…...

OpenStego:专业隐写术工具实现安全数据隐藏与版权保护

OpenStego&#xff1a;专业隐写术工具实现安全数据隐藏与版权保护 【免费下载链接】openstego OpenStego is a steganography application that provides two functionalities: a) Data Hiding: It can hide any data within an image file. b) Watermarking: Watermarking ima…...

RVC效果对比评测:vs So-VITS-SVC、DiffSinger、VITS2

RVC效果对比评测&#xff1a;vs So-VITS-SVC、DiffSinger、VITS2 1. 引言&#xff1a;为什么需要语音转换模型&#xff1f; 你有没有想过&#xff0c;用自己的声音唱出偶像的歌是什么感觉&#xff1f;或者&#xff0c;为你的视频角色配上另一个人的声音&#xff1f;这就是语音…...

Asian Beauty Z-Image Turbo 学术研究:基于其生成能力的视觉认知心理学实验设计

Asian Beauty Z-Image Turbo 学术研究&#xff1a;基于其生成能力的视觉认知心理学实验设计 最近和几位做认知心理学的朋友聊天&#xff0c;他们提到一个挺头疼的问题&#xff1a;做面部表情识别或者情绪感知这类实验&#xff0c;找合适的视觉刺激材料太费劲了。要么是公开的数…...

HWA_03 leetcode874模拟行走机器人

题目map方法的作用解题思路 class Solution:def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:#初始化结果result 0#从原点0&#xff0c;0位置开始出发x0y0#机器人前进的方向#初始方向:正北#0表示向北#1表示向东#2表示向南#3表示向西direction0…...

你的热电偶读数总跳?可能是50/60Hz工频干扰!STM32驱动MAX31856的滤波配置避坑指南

热电偶读数跳变&#xff1f;50/60Hz工频干扰的精准诊断与MAX31856滤波实战 工业现场的温度测量工程师们&#xff0c;是否经常遇到这样的困扰&#xff1a;明明硬件连接正确&#xff0c;STM32与MAX31856的驱动代码也按手册编写&#xff0c;但热电偶读数却像心电图一样上下跳动&am…...

5步精通抖音批量下载工具:从单视频到整主页的高效解决方案

5步精通抖音批量下载工具&#xff1a;从单视频到整主页的高效解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback s…...

Word样式与多级列表深度绑定指南:让你的标题编号“活”起来,增删章节不再乱

Word样式与多级列表深度绑定指南&#xff1a;让你的标题编号“活”起来&#xff0c;增删章节不再乱 每次在Word中调整文档结构时&#xff0c;你是否经历过这样的崩溃瞬间&#xff1a;精心排版的章节编号突然乱成一团&#xff0c;原本整齐的"1.1"变成了毫无规律的&quo…...

基于RexUniNLU的Java企业级文本分析系统构建指南

基于RexUniNLU的Java企业级文本分析系统构建指南 1. 引言 想象一下这样的场景&#xff1a;你的电商平台每天收到数万条客户反馈&#xff0c;客服团队需要手动分类处理&#xff1b;法务部门每天要审核大量合同&#xff0c;寻找关键条款&#xff1b;市场团队需要从海量评论中提…...

[RL]强化学习指导搭建IC2E核反应堆

Minecraft 工业2 实验版核反应堆计算 强化学习模块训练路径 最近在玩Minecraft IC2 Classic&#xff0c;但是对于摆核反应堆总是感觉不是很得心应手&#xff0c;不管怎么摆效率都很低&#xff0c;为了解决这个问题&#xff0c;所以我写了一个强化学习的模块&#xff0c;让神经网…...

WarcraftHelper:解决经典游戏兼容性问题的技术增强方案

WarcraftHelper&#xff1a;解决经典游戏兼容性问题的技术增强方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 当玩家在现代硬件上运行魔兽争霸II…...