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

文章目录

  • 一,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; // 实际数值1int num2 = 3; // 实际数值2// 函数调用,传递实参:num1 和 num2int 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.0return 0;
}

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

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

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

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

相关文章

Android使用zxing生成二维码

效果图如下&#xff1a; **前提&#xff1a;导入zxing的jar后开始操作&#xff0c;老规矩最后有源码&#xff0c;作者布局默认相对布局。 第一步&#xff1a;定义二维码的长宽高及图片控件** 第二步&#xff1a;实例化QRCodeWriter后利用for循环将二维码画出来&#xff0c;然后…

用Visual Studio调试CMake项目并生成Visual Studio工程

一. 在Windows系统上安装CMake 访问CMake官方网站https://cmake.org/download&#xff0c;或通过文末链接下载&#xff1a;在下载页面上&#xff0c;找到并点击“Download”链接以获取最新的稳定版本的CMake。请注意&#xff0c;虽然新版本可能包含更多功能和改进&#xff0c;…

关于DrawTools的分析- 一个优秀的C#开源绘图软件

国外大佬&#xff0c;曾经写过两个关于DrawTools相关的开源绘图软件。 我更新了一个优化的版本如下图&#xff0c;稍后会发布更新给大家。 需要的用户可发邮件给我 448283544qq.com 应用于AGV地图编辑器如下&#xff1a; 那么这个优于很多普通的画布软件&#xff0c;包含点、…

qt 简单实验 读取json格式的配置文件

1.概要 2.代码 //#include "mainwindow.h"#include <QApplication> #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QDebug> //读取json数据的配置文件QJsonObject readJsonConfigFile(const QString …

iptables动作总结

ACCEPT动作 将数据包放行&#xff0c;进行完此处理动作后&#xff0c;将不再比对当前链的其它规则&#xff0c;直接跳往下一个规则链。 范例如下&#xff1a; #新增自定义链TEST_ACCEPTiptables -t filter -N TEST_ACCEPT#新增自定义链TEST_ACCEPT2iptables -t filter -N TES…

0基础学习线段树

前言&#xff1a; 线段树&#xff1a;用树来表示一个一个的线段区间。 1、为什么要使用线段树&#xff1f; 题目&#xff1a;给定一个数组nums&#xff0c;我们有两种下面两种操作 1、查询nums数组下标i到下标j的和&#xff1b; 2、将nums数组指定下标的值改为指定的一个新…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-28批量规范化

28批量规范化 """可持续加速深层网络的收敛速度""" import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as pltdef batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):""&quo…

Swift 中的动态数组

Swift 的 Array 类型是一种强大而灵活的集合类型&#xff0c;可以根据需要自动扩展或缩减其容量。 动态数组的基本概念 Swift 中的数组是基于动态数组&#xff08;dynamic array&#xff09;的概念实现的。动态数组能够根据需要自动调整其容量&#xff0c;以容纳新增的元素&a…

Benchmarking Panoptic Scene Graph Generation (PSG), ECCV‘22 场景图生成,利用PSG数据集

2080-ti显卡复现 源代码地址 Jingkang50/OpenPSG: Benchmarking Panoptic Scene Graph Generation (PSG), ECCV22 (github.com) 安装 pytorch 1.7版本 cuda10.1 按照readme的做法安装 我安装的过程如下图所示,这个截图是到了pip install openmim这一步 下一步 下一步 这一步…

C语言 | Leetcode C语言题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {int* ret (int*)malloc(sizeof(int) * 2);*returnSize 2;int low 0, high numbersSize - 1;while (low < high) {int sum numbers[low] numbers[high]…

如何设置MySQL远程访问权限?

MySQL是一种流行的关系型数据库管理系统&#xff0c;它广泛应用于各种Web应用程序和数据驱动的应用中。在默认情况下&#xff0c;MySQL只允许本地访问&#xff0c;为了能够从远程服务器或客户端访问MySQL数据库&#xff0c;我们需要进行一些额外的设置和配置。 安装和配置MySQ…

在阿里云使用Docker部署MySQL服务,并且通过IDEA进行连接

阿里云使用Docker部署MySQL服务&#xff0c;并且通过IDEA进行连接 这里演示如何使用阿里云来进行MySQL的部署&#xff0c;系统使用的是Linux系统 (Ubuntu)。 为什么使用Docker? 首先是因为它的可移植性可以在任何有Docker环境的系统上运行应用&#xff0c;避免了在不通操作系…

【html】用html+css实现银行的账户信息表格

我们先来看一看某银行的账户信息表格 我们自己也可以实现类似的效果 效果图: 大家可以看到&#xff0c;其实效果差不多 接下来看看我们实现的代码 源码&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"&…

机械师硬盘数据清空怎么办?机械师硬盘数据清空怎么恢复

机械师硬盘数据清空怎么恢复&#xff1f;随着数字化时代的到来&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;硬盘数据的意外清空往往会给我们带来极大的困扰。本文将探讨在机械师硬盘数据清空后&#xff0c;我们应该如何快速有效地恢复数据。 图片…

二本毕业,我是如何成为BAT-安卓开发工程师?

1.对基础原理不断挖掘 进入公司&#xff0c;我的职位是Linux应用开发工程师&#xff0c;做App网络传输模块&#xff0c;本质上就是把本地的数据通过socket传输到服务端。用到的技术是C语言&#xff0c;网络编程&#xff0c;多线程编程。 那时是最痛苦的几个月&#xff0c;因为…

[FreeRTOS 功能应用] 互斥访问与回环队列 功能应用

文章目录 一、基础知识点二、代码讲解三、结果演示四、代码下载 一、基础知识点 [FreeRTOS 基础知识] 互斥访问与回环队列 概念 [FreeRTOS 内部实现] 互斥访问与回环队列 [FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析 本实验是基于STM32F103开发移植FreeRTOS实时操作系…

解决WebStorm中不显示npm任务面板

鼠标右键项目的package.json文件&#xff0c;然后点击show npm scripts选项。 然后npm工具窗口就显示了&#xff1a;

02--MySQL数据库概述

目录 第10章 子查询 10.1 SELECT的SELECT中嵌套子查询 10.2 SELECT的WHERE或HAVING中嵌套子查询 10.3 SELECT中的EXISTS型子查询 10.4 SELECT的FROM中嵌套子查询 第11章 MySQL支持的数据类型 11.1 数值类型:包括整数和小数 1、整数类型 2、bit类型 3、小数类型 11.2…

【Python系列】探索 NumPy 中的 mean 函数:计算平均值的利器

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

软件串口接收子程序

代码; stduart.c /*《AVR专题精选》随书例程3.通信接口使用技巧项目&#xff1a;使用延时法实现半双工软件串口文件&#xff1a;sfuart.c说明&#xff1a;软件串口驱动文件作者&#xff1a;邵子扬时间&#xff1a;2012年12月13日*/ #include "sfduart.h"// 循环中延…