零基础学C语言——函数(c语言函数怎么学)
liebian365 2025-02-04 15:02 13 浏览 0 评论
这是一个C语言系列文章,如果是初学者的话,建议先行阅读之前的文章。笔者也会按照章节顺序发布。
上一篇我们介绍了表达式和语句,这一篇我们介绍C语言中的函数。
首先,我们先来看个例子:
int add(int num1, int num2)
{
return num1 + num2;
}
上面这段内容就是一个完整的C语言函数。
函数的功能
函数与我们在数学中了解到的函数概念比较相似。粗略地讲,在数学中,函数是用来完成某种功能的,例如,sin、cos等。在C语言中,与之类似,都是用于封装某种功能的。函数不但将功能封装成小的个体函数,还可以在需要的地方直接调用,避免通篇复制功能细节代码。
上面的例子就是计算两数相加的结果。当我给出具体的数值,例如1和2,那么这个函数就会返回3,其中1和2我们称作输入参数,3称作函数的输出(或者 返回值)。
读过码哥前面几篇文章的读者可能记得,在表达式一节中,函数调用表达式的值就是函数返回值,我们将在下面进一步介绍。
函数命名规范
在C语言中,函数的命名规范与变量的命名规范是一样的,都是以下划线(_)或字母开头,后续字符可以是字母、数字、下划线。下面给出一些例子:
_abc 符合命名规范
123abc 不符合规范
abc 符合规范
~abc 不符合规范
函数定义的一般形式
由于在C语言中有多种基础数据类型,因此,函数的参数类型、参数数量、返回值类型都有所不同。除去这些不同,其他部分则是有统一形式的。
返回值类型 函数名 (参数1, ...)
{
各种语句
return 返回值;
}
其中:
函数参数
根据功能需要可有参数也可以没有参数。例如:
int get10(void)
{
return 10;
}
//或者
int get10()
{
return 10;
}
对于不需要参数的函数,可以在参数列表处写void,也可以省略不写。
返回值
如果函数不需要返回值,那么return语句可以省略,但是函数 返回值类型 处要写void。
如果不写返回值类型,那么编译器默认为int型。
void print_help(void)
{
printf("Help information\n");
}
或
void print_help(void)
{
printf("Help information\n");
return;
}
其中,printf是C标准IO库中定义的终端输出函数,初学者暂时不必纠结于此,只记住这个函数可以将里面的字符串部分输出到屏幕上。
可能有的读者会发现,笔者从来没说过基础数据类型中有字符串类型。是的,C语言中确实没有这个基础类型,字符串在C中都是以字符数组出现的,关于数组相关内容,笔者将会在后面文章中讲解。
函数的声明
函数的声明是用来告知编译器,函数在当前代码文件或者其他代码文件中有定义。
为何有这种需求呢?我们来看下面这个例子:
int main(void)
{
foo();
}
void foo(void
)
{
}
这个例子的功能是,在main函数中调用foo函数。
将代码直接写入文件然后编译,编译器会报错,大致是说main中的foo和外面的foo类型冲突。一般导致这样的报错有两种原因:
- 函数名称重复了,即定义了两个同名函数,且返回值类型或参数类型、参数数目不同
- 函数没重复但是缺少函数声明
这里,是因为第二个原因导致的。为何是第二个呢?
由于因为C语言编译器在处理源文件(即代码文件)时,是由上至下,由左至右的读取和处理文件内容的,因此就会对函数定义的位置、顺序较为敏感。在上面的这个例子中,当处理到main时,编译器并不知道这个文件中定义了foo函数,因此当看到main函数中调用了foo函数时就会误将调用当函数声明。而后当读取到foo函数定义时,发现和之前的声明不一致(返回值类型)。
解决方法很容,见下例:
void foo(void);
int main(void)
{
foo();
}
void foo(void)
{
}
再次编译即可通过。
我们在main函数定义前加入的内容就是foo函数的声明。
函数声明也有其一般形式:
返回值类型 函数名(参数列表);
其中,参数列表部分,若无参数可以省略不写或者写void,与定义一样。但如果有参数,则可省略参数名,亦可不省略。例如:
int add(int num1, int num2);
或
int add(int, int);
都是可行的,因为编译器在读取声明时只关心函数参数的类型,而不关心具体名字。
函数调用
上面我们其实已经见过函数的调用了。下面先说其一般形式:
函数名(输入参数列表);
例如,
add(1, 2); //调用最开始定义的add函数,函数有返回值,但是并未使用到
int result = add(1, 2); //调用add函数,并将返回值赋给变量result,result的值为3
函数参数
在C语言中,我们将函数定义中的参数称做形式参数(形参),函数调用中的参数称作实际参数(实参)。
上面的例子中,1和2就是实参,而定义中的num1和num2就是形参。
在一些关于C语言的文章中,有人说参数的传递包含两种方式,这点笔者不敢苟同。在C语言中只有一种传参方式——值传递。
其中,参数传递是指:调用函数时,将实际参数传递给被调用函数的形式参数,也可以看作是一种映射过程。
值传递(此处内容建议初学者在阅读后续数组和指针文章后再来阅读):
值传递最直接的理解就是传递数值。
在C语言中,基础数据类型的参数传递比较显而易见,例如上面add调用的例子,传递的是两个整数值。但是数组的传递,对于一些写惯脚本语言的开发者来说会不太习惯。看一个例子:
int new_add(int *nums)
{
return nums[0] + nums[1];
}
int main(void)
{
int nums = {1, 2};
int result = new_add(nums);
return 0;
}
这里,在main中定义了一个整型数组,其中含有两个元素分别是1和2。我要将数组传给new_add函数,然后让函数返回两个元素相加的结果。此时,我们传递给new_add函数的参数并非完整数组的拷贝,而是数组的首地址,即指针。而指针也是一个值(可被看作无符号长整型),而非一种结构。
main函数
main函数也被叫做主函数,每一个生成可执行程序的C语言工程都一定有一个main函数,缺失主函数,编译器会报错。所有C程序都会从main函数开始执行。
在UNIX系统下(Linux、OSX等),主函数的形式如下:
int main(void)
{
...//具体内容
return 0;//具体返回值可自己定但一定是整数
}
或
int main(int argc, char *argv[])
{
...//具体内容
return 0;//具体返回值可自己定但一定是整数
}
其中,argc是命令行参数个数,而argv则是每一个命令行参数内容组成的字符指针数组,例如这个源文件生成的可执行程序叫a,那么在命令行下执行:
$ ./a argument1 2 3
此时,argc为4,而argv的内容为: "./a", "argument1", "2", "3"这4个字符数组,即可执行程序名和其命令行参数。关于数组和指针的话题我们后面文章中会介绍。
递归函数
下面我们介绍一种特殊的函数调用方式。先来看个例子:
void recursive_func(int i)
{
if (i > 3)
return;
recursive_func(++i);
}
int main(void)
{
recursive_func(0);
return 0;
}
在这个例子中,main函数中调用了一个名为recursive_func的函数,而recursive_func函数就是一个递归函数,即在函数中调用其自身。在main中传给recursive_func的参数i的值为0,然后在recursive_func内部每次调用自身时都将函数参数自增1,如此一层层调用下去。当i增加到3时,函数停止自身调用,然后逐层返回。
本篇涉及一些后续文章中的内容,实在无法避免,建议初学者在通读后,先继续阅读后续文章,然后再返回本篇复读一遍。
喜欢的读者可以关注码哥,也可以在下方留言评论,如果有不清楚的地方也可以私信码哥,我会第一时间回复。
感谢阅读!
相关推荐
- 4万多吨豪华游轮遇险 竟是因为这个原因……
-
(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...
- “菜鸟黑客”必用兵器之“渗透测试篇二”
-
"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...
- 科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白
-
作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...
- 麦子陪你做作业(二):KEGG通路数据库的正确打开姿势
-
作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...
- 知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势
-
智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...
- 每日新闻播报(September 14)_每日新闻播报英文
-
AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...
- 香港新巴城巴开放实时到站数据 供科技界研发使用
-
中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...
- 5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper
-
本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...
- Qt动画效果展示_qt显示图片
-
今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...
- 如何从0到1设计实现一门自己的脚本语言
-
作者:dong...
- 三年级语文上册 仿写句子 需要的直接下载打印吧
-
描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...
- C++|那些一看就很简洁、优雅、经典的小代码段
-
目录0等概率随机洗牌:1大小写转换2字符串复制...
- 二年级上册语文必考句子仿写,家长打印,孩子照着练
-
二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)