C语言入门系列:初识函数

news2024/11/25 15:56:01

文章目录

  • 一,C语言函数与数学函数的区别
    • 1,回忆杀-初中数学
    • 2,C语言中的函数
  • 二, 函数的声明
    • 1,函数头
      • 1.1,函数名称
      • 1.2,返回值类型
      • 1.3,参数列表
    • 2,函数体
      • 2.1,函数体
      • 2.2,return语句
  • 三,main函数
  • 四,函数的参数与传递方式
    • 1,实参和形参
      • 1.1,函数定义(含形参)
      • 1.2,函数调用(使用实参)
    • 2,参数传递方式
      • 2.1,值传递
      • 2.2,引用传递
  • 五,函数原型与预声明
    • 1,什么是函数原型
    • 2,为什么函数要预声明
  • 六,函数的返回值

一,C语言函数与数学函数的区别

1,回忆杀-初中数学

说起函数这个词,大多数程序员应该是耳熟能用,初中数学就开始学习函数,到现在已经有了多年的函数经验。

对于下面这张图,想必大家并不陌生吧。

在这里插入图片描述
以最简单的一元一次函数为例:

y=3x

在上述函数表达式y = 3x中,组成部分如下:

  • y 被称为因变量(Dependent Variable)或函数值,它依赖于自变量x的值。
  • x 被称为自变量(Independent Variable),它是你可以自由选择的输入值。
  • 3 是系数(Coefficient),在这个线性函数中表示自变量x每增加1单位,因变量y增加的数量。
  • = 表示等于,表明两边的量在给定x的值时是相等的。
  • y = 3x 整体构成了一个函数关系,其中y是x的函数,通常会定义一个特定的函数名称,如f(x),写作f(x) = 3x,这里f即为函数名。

2,C语言中的函数

尽管C语言函数借鉴了数学函数的思想,两者间存在根本差异。

数学函数专注于描述数学关系,无需考虑实现细节,而C语言函数则是实现特定任务的代码集合,需关注数据类型、内存管理等编程细节。

数学函数的输入输出都是数字,C语言中的函数可以处理的数据除了数字之外,还可以是字符、指针,甚至是另一个函数。

二, 函数的声明

函数是C语言中一种可以被重复使用的对象,包含一段可以重复执行的代码。函数可以接收不同的参数值,经过相同的逻辑处理,返回对应的结果。

C语言函数由函数头函数体两部分组成:

  • 函数头包括函数返回类型、函数名和参数列表(如果有)。
  • 函数体包含执行语句,实现函数的具体功能。

下面是一个函数的示例。

int plus1(int num) {
  return num + 1;
}

上面的代码声明了一个函数plus1(),包含函数头和函数体。

1,函数头

1.1,函数名称

上面代码示例定义了名为plus1的函数。

1.2,返回值类型

函数名plus1前面的int指明了函数的返回值类型,这个函数将返回一个整数。

当然,函数可以没有返回值,没有返回值时,返回值类型为void

void showNum(int num) {
  printf("num=%d", num);
}

1.3,参数列表

函数名plus1后面的圆括号里面就是参数列表,每个参数由参数类型和参数名组成,可以有多个参数,plus1(int num)表示这个函数有一个整数参数num

2,函数体

2.1,函数体

函数体位于参数列表之后,包裹在一对大括号里面,下图中蓝色部分就是函数体。

在这里插入图片描述

注意:大括号前后都不需要加分号。

2.2,return语句

return语句是函数体中的特殊语句,它给出函数的返回值,程序运行到return语句,表示当前函数运行完毕,完成函数调用,返回到调用函数处。

需要注意的是,函数可以没有返回值,所以return语句不是必须得。如果函数没有返回值,可以省略return语句,或者写成return;

void showNum(int num) {
  printf("num=%d", num);
  // 省略return
}

等价于:

void showNum(int num) {
  printf("num=%d", num);
  return;
}

三,main函数

一个C程序至少包含一个函数,这个函数就是main()函数,它是程序的入口点。

main()负责调用其他函数,完成程序的主要任务。

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0; // 程序正常结束
}

main()函数的声明和普通函数并无区别,也包含函数头和函数体,函数头包含返回值类型、函数名称、参数列表,函数体包含return语句。

正常情况下,如果main()里面省略return 0这一行,编译器会自动加上,即main()的默认返回值为0。所以,写成下面这样,效果完全一样。

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    // 省略return 0; 程序正常结束
}

四,函数的参数与传递方式

1,实参和形参

在C语言中,函数的参数分为形式参数(形参,Formal Parameters)和实际参数(实参,Actual Parameters)。

形参是在函数定义中使用的占位符,代表将来调用该函数时传递进来的值。

实参则是函数调用时实际传递给函数的具体值或变量。

下面通过一个简单的示例来说明这一概念。

1.1,函数定义(含形参)

// 函数声明和定义
// 形参:a 和 b 分别代表将要相加的两个整数
int addNumbers(int a, int b) {
    int sum = a + b; // 使用形参a和b计算和
    return sum; // 返回计算结果
}

在这个例子中,ab是形式参数,它们在函数定义中作为接收外部数据的占位符。

1.2,函数调用(使用实参)

#include <stdio.h>

int main() {
    int num1 = 5; // 实际数值1
    int num2 = 3; // 实际数值2
    
    // 函数调用,传递实参:num1 和 num2
    int result = addNumbers(num1, num2);
    
    // 输出结果
    printf("The sum of %d and %d is %d\n", num1, num2, result);
    
    return 0;
}

main函数中,当调用addNumbers函数时,num1num2是实际参数。

这两个实参的值(5和3)会被传递给对应的形参ab,函数内部使用这些值进行计算。

2,参数传递方式

函数参数用于向函数传递数据,C语言支持两种传递方式:值传递和引用传递。

2.1,值传递

传递参数的副本,函数内对参数的修改不影响原变量。

void swapByValue(int x, int y) {
    int temp = x;
    x = y;
    y = temp; // 交换操作仅影响局部副本
}

int main() {
    int a = 5, b = 10;
    swapByValue(a, b);
    printf("a = %d, b = %d\n", a, b); // 输出不变:a = 5, b = 10
}

上述代码,通过值传递调用函数swapByValue(int x, int y),表面上起到了交换a和b的值的作用,实则并未改变a和b的值。

这是因为调用函数时是将ab的值复制一份后,赋值给形参变量xy,之后对xy的操作不会影响ab的值。

2.2,引用传递

传递参数的地址,通过指针实现,函数内可通过地址修改原变量。

void swapByReference(int* x, int* y) {
    int temp = *x;
    *x = *y;
    *y = temp; // 实际交换变量的值
}

int main() {
    int a = 5, b = 10;
    swapByReference(&a, &b);
    printf("a = %d, b = %d\n", a, b); // 输出交换后:a = 10, b = 5
}

上述代码,通过值传递调用函数swapByValue(int* x, int* y),表面上起到了交换a和b的值的作用,实际上的确起到了这个作用。

这是因为调用函数时是将ab的地址传递给了指针变量xy,函数体内通过运算符*xy进行运算,本质上操作xy指向的内存中的数据,也即是变量ab的数据。

五,函数原型与预声明

1,什么是函数原型

函数原型是在函数定义之前提供的一种声明方式,用于告诉编译器函数的返回类型、名称和参数列表。

// 函数原型
int max(int, int);

int main() {
    int larger = max(10, 20);
    printf("Larger number is: %d\n", larger);
    return 0;
}

// 函数定义
int max(int x, int y) {
    return (x > y) ? x : y;
}

2,为什么函数要预声明

我们知道,函数一定要先声明后使用。

我们还知道,main()函数是C程序第一个运行的函数,这就导致所有的函数都必须在main()函数之前声明。

void func1(void) {
}

void func2(void) {
}

int main(void) {
  func1();
  func2();
  return 0;
}

上面代码中,main()函数必须在最后声明,否则编译时会产生警告,找不到func1()func2()的声明。

但是,这样编写代码有很多实践上的困难:

  • 一方面,main()是整个程序的入口,也是主要逻辑,放在最前面更好。
  • 另一方面,对于函数较多的程序,保证每个函数的顺序正确,会变得很麻烦。

C 语言的解决方案是在程序文件最前面给出函数原型,函数就可以先使用、后声明。

所谓函数原型,就是函数头,不需要函数体,函数体包含在之后的完整函数声明中。

int twice(int);

int main(int num) {
  return twice(num);
}

int twice(int num) {
  return 2 * num;
}

上面示例中,函数twice()的完整声明是放在main()后面,但是代码头部先给出了函数原型,所以可以正确编译。

只要提前给出函数原型,函数具体的实现放在哪里,就不重要了。

函数原型包括参数名也可以,虽然这样对于编译器是多余的,但是阅读代码的时候,可能有助于理解函数的意图。

int twice(int);

// 等同于
int twice(int num);

上面示例中,twice函数的参数名num,无论是否出现在原型里面,都是可以的。

注意,函数原型必须以分号结尾。

六,函数的返回值

函数通过return语句返回一个值给调用者。

返回类型在函数声明和定义中指定,可以是任何基本类型、结构体、甚至指针。

float average(int a, int b) {
    return (a + b) / 2.0f;
}

int main() {
    float avg = average(3, 7);
    printf("Average is: %.1f\n", avg); // 输出:Average is: 5.0
    return 0;
}

void类型的函数表示不返回任何值。

void showNum(int num) {
    printf("num=%d", num);
}

int main() {
    int num = 10;\
    showNum(10);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1852510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea右侧找不到Maven,在View-> Tool Windows下也找不到

正常情况Idea右侧没有Maven&#xff0c;只需去View -> Tool Windows 目录中找到Maven并点击Maven&#xff0c;Idea右侧就会出现 问题&#xff1a; idea右侧找不到Maven&#xff0c;在View -> Tool Windows 目录中也找不到Maven&#xff0c;下图 全局搜索ctrl N&#xff…

数据结构历年考研真题对应知识点(栈和队列的应用)

目录 3.3栈和队列的应用 3.3.2栈在表达式求值中的应用 【中缀表达式转后缀表达式的过程(2012、2014)】 【栈的深度分析(2009、2012)】 【用栈实现表达式求值的分析(2018)】 3.3.3栈在递归中的应用 【栈在函数调用中的作用和工作原理(2015、2017)】 3.3.5队列在计算机系…

苹果智能和人工智能最大化

苹果智能和人工智能最大化 除了苹果公司&#xff0c;还没有人真正使用过苹果的智能功能。它要到秋天才会分阶段发布&#xff0c;即使到那时&#xff0c;它也无法在80%或90%的iPhone安装基础上运行&#xff0c;因为它需要只有iPhone 15 Pro才能使用的设备上处理功能。没有什么能…

如何从magento1迁移到magento2

m2相较m1 变化可以说非常大&#xff0c;相当于从头到位都改写一遍&#xff0c;更现代化&#xff0c;更优雅。除了数据库表变化不是很大。 主要迁移的内容有&#xff1a; 1&#xff0c;主题 2&#xff0c;插件(自己开发的或者第三方插件) 3&#xff0c;数据库 主题 不能迁移到m…

如何在Windows 11和10上清除更新缓存?这里提供了几种方法

​Windows 11和Windows 10都可以非常轻松地清除Windows更新缓存。可以使用图形方法或命令行选项删除保存的更新文件。我们将向你展示你的可用选项。 为什么要清除Windows更新缓存 你可能希望清除Windows更新缓存的原因有很多。 你可能在查找或安装更新时遇到问题,清除缓存通…

如何恢复丢失的文件?免费为 Mac 恢复数据

丢失 Mac 上的重要文件是一件非常痛苦的事情。无论是重要的工作文件、重要文件还是心爱的照片&#xff0c;意外删除它们或出现系统错误都会非常令人沮丧。别担心&#xff1b;有办法&#xff1a;奇客数据恢复Mac版。这款免费的 Mac 文件恢复软件就像您文件的救星 - 当出现问题时…

每日一练:攻防世界:5-1 MulTzor

一、XorTool 基于 XOR&#xff08;异或&#xff09;运算实现。它可以帮助您快速地对文本、二进制文件进行加密解密操作。 认识XorTool工具&#xff1a; 让我们先去认识一下工具&#xff1a; xortool.py 是基于 python 的脚本&#xff0c;用于完成一些 xor 分析&#xff0c;…

持久化、主从 、分片、哨兵

目录 持久化 RDB&#xff08;存数据&#xff09; 使用场景 bgsave 使用方法 原理 AOF&#xff08;存命令&#xff09; 使用方法 原理 bgrewriteaof AOF和RDB 主从集群 搭建 数据同步原理(slave宕机&#xff09; 全量同步 增量同步 集群优化 总结 哨兵机制&…

JAVA学习过程中遇到的问题

前言 记录学习过程中遇见的各种问题。希望对你有帮助。 目录 前言 1、新建maven项目时&#xff0c;archetype项目骨架加载慢 2、maven的pop.xml添加依赖项无法检测到 3、java: 无效的目标发行版: 20 4、idea添加maven依赖太慢 5、CTRLCV复制粘贴太慢 6、Swagger写接口文…

手持弹幕LED滚动字幕屏夜店表白手灯接机微信抖音小程序开源版开发

手持弹幕LED滚动字幕屏夜店表白手灯接机微信抖音小程序开源版开发 专业版 插件版 手持弹幕小程序通常提供多种功能&#xff0c;以便用户在不同的场合如夜店、表白、接机等使用。以下是一些常见的功能列表&#xff1a; 文本输入&#xff1a; 输入要显示的文字内容&#xff0c;…

Android招聘市场技术要求越来越高,从事三年开发是否应该考虑转行?

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训&#xff0c;学会这小块知识就能随便找到不错的工作了。 不过很显然现在远远不够了&#xff0c;拒绝无休止的CV&#xff0c;亲自去项目实战&#xff0c;读源码&#xff0c;研究原理吧&#xff01; 《Framework精编…

HeidiSQL导入与导出数据

HeidiSQL两种导入与导出数据的方法&#xff1a;整个库复制&#xff0c;和仅复制数据 一 整个库复制 1 选中需要导出的数据库(这里是MyDBdata)&#xff0c;点击导出为SQL脚本。 2 按照如图进行选择 3 选做&#xff1a;删除当前数据库【如果有】 -- 删除数据库 USE mysql; D…

Linux-cp命令实现-系统调用和函数区别-文件截断-文件空洞

1、实现CP命令 vimdiff file1 file2 vimdiff是Vim编辑器的一个功能&#xff0c;主要用于比较两个或多个文件之间的差异&#xff0c;并在一个Vim窗口中显示这些差异。这个功能特别适合用于比较修改前后的文件&#xff0c;或者比较两个不同版本的文件。 注意&#xff1a;用…

SD卡无法读取:原因解析与数据恢复策略

一、SD卡无法读取的尴尬场景 在数字化日益普及的今天&#xff0c;SD卡作为便携式存储设备&#xff0c;广泛应用于各类电子设备中。然而&#xff0c;当您急需访问SD卡中的数据时&#xff0c;却发现设备无法读取SD卡&#xff0c;这无疑是一个令人沮丧的场景。SD卡无法读取可能表…

【已解决】在IDEA中使用Git拉取代码时提示:Can‘t update / master has no tracked branch

文章目录 问题描述原因分析解决方案 问题描述 在IDEA中使用Git拉取代码&#xff0c;尝试更新本地项目代码&#xff0c;提示 " Cant update / master has no tracked branch "&#xff0c;如下图所示&#xff1a; 原因分析 出现上述问题意味着本地名为master的分支&…

Google Earth Engine(GEE)——ui.DateSlider时间进度条的设置

结果 函数: ui.DateSlider(start, end, value, period, <

排序不等式——AcWing 913. 排队打水

排序不等式 定义 这主要涉及到利用 C 的排序操作对数据进行排序后&#xff0c;基于排序结果进行一些分析和处理。 运用情况 对一组数据进行排序后&#xff0c;根据排序后的顺序来解决一些与顺序相关的问题&#xff0c;比如选取最大或最小的若干个元素。在一些需要按照特定顺…

前端项目结构介绍与Vue-cli(脚手架)环境搭建

传统的前端项目结构 一个项目中有许多html文件 每一个html文件都是相互独立的 如果需要在页面中导入一些外部依赖的组件(vue.js,elementUI),就需要在每一个html文件中引用都导入,十分的麻烦 而且这些外部组件都需要在其官网中自行下载,也增加了导入的繁琐程度 当今的前端项…

NeRF从入门到放弃5: Neurad代码实现细节

Talk is cheap, show me the code。 CNN Decoder 如patch设置为32x32,patch_scale设置为3&#xff0c;则先在原图上采样96x96大小的像素块&#xff0c;然后每隔三个取一个像素&#xff0c;降采样成32x32的块。 用这32x32个像素render feature&#xff0c;再经过CNN反卷积预测…

【C语言】关于字符串函数的使用及模拟实现(1)

一、字符串追加 1.1 库函数srecat的使用 1.2 库函数strncat的使用 1.3 模拟实现库函数 strcat 及 strncat 由上可知&#xff0c;字符串追加的原理是找到所添加字符串的 \0 位置&#xff0c;再对其进行添加。 代码1、 代码2、 二、字符串查找 2.1 库函数strstr的使用 使用…