C 语言程序设计---函数

一篇入门级别的C语言函数,值得一看。

图片发自简书App

上次写了 C 语言入门级别的指针,这篇写函数,指针和函数在一起使用,更有意思,这也才能最大程度的发挥指针的作用。


基本概念


C 语言是一个函数语言,函数相当于”工厂“,具有”来料加工“的能力。

1sqrt(2.0);

2//sqrt()函数,接收 2.0 这个来料,并把它加工成 1.414...这样的结果。


1、

函数的分类

A、按 main() 和其它函数:主函数、其它函数

B、按作者分:系统函数(库函数)、用户自定义函数(我们自己写的);无论是库函数,还是用户自定义函数,其产生过程和调用,都应遵循相同的编程原则;

C、按函数调用关系分:主调函数、被调函数;

D、函数按参数个数划分:定参函数、不定参函数。


定参函数,参数个数固定;不定参函数,参数个数不确定;定参函数又分为有参函数和无参函数。

1printf("%d%d%d", a, b, c);  //4 个参数

2printf("Hello\n");  //1 个参数

3//所以 printf() 是一个不定参函数

4//若函数无参,则可以用 void 加以明确声明

5void main(void){}  //名称为 main 的函数,无返回值,无参数


2、

函数的产生和使用过程(步骤)


A、函数声明

B、函数定义

C、函数调用


函数声明:

(1)、确定的函数名称,函数名称是用以区分其它函数的标志,是这个函数的”入口“地址常量。

(2)、说明函数的返回值类型,sqrt(2.0) 的计算结果为 1.414,这个 1.414 就是所谓的返回值;

函数可以没有返回值,此时该函数返回值类型必须明确的写成:void;

返回值是由被调函数返回给主调函数的数值;函数若有返回值,最多只能有一个返回值;

(3)、说明函数的参数,参数个数以及每个参数的数据类型;函数在声明时,可以只说明参数类型,而缺省相关变量。

1int fun(int n);

2int fun(int);

//以上函数声明都是正确的


函数定义:

就是函数的编程,实现函数的功能,主要包含函数首部和函数体。

函数首部包括:函数返回值类型、函数名称、以及形参;

函数体是由 {} 括起来的语句组成。

1int fun(int m){}


注意:

(1)、若函数明确声明不是 void,则该函数必须以 {return 表达式;} 语句结束,并且,表达式类型必须与函数的返回值类型完全一致!

若函数返回值为 void,则可以写 return; 语句结束,也可以缺省这条语句。

特别强调:return (表达式); 这样的写法,在概念上是一种坏习惯,在 C 语言中,xxx() 出现,代表的是对 xxx() 函数的调用,上面的写法好像就是在说 return 是函数名称,而实际上,return 是关键字!


(2)、关于 return

A、它是函数运行结束的语句,在这条语句后出现的任何其它语句,是绝对不会运行到的。

1if (条件) {

2    return ;

3}

4语句1;

5//明显,只有条件不成立,才能执行语句1

6}


B、所谓的函数运行结束的 return(返回),是“返回”到调用它的函数的下一条语句继续执行。

C、所谓的 return 表达式; 意思是,返回到主调函数,并用“表达式”的值,替代主调函数中,关于这个函数的调用部分内容。


函数调用:

1#include <stdio.h>

2

3int add (int a, int b);  //函数声明

4int add (int a, int b) {  //函数定义

5    return a + b;

6}

7int main (void) {

8    int a;

9    int b;

10    int sum;

11

12    scanf("%d%d", &a, &b);

13    sum = add(a, b);  //函数调用

14

15    return 0;

16}


形参与实参


1、

形参与实参的定义

A、形参出现在函数定义的“函数首部”的括号中;

B、实参出现在函数调用的括号中;

C、实参有三种形式:常量、变量、表达式;

D、形参只有一种形式:变量。

1int fun (int num);

2int fun (int num) {  //这个 num 就是形参  这块是函数定义

3  ...

4}

5

6int main (void) {

7    int a;

8

9    a = fun(5);  //这个 5 就是实参  这块是函数调用

10}


形参只有变量这一种形式,不可能出现常量,甚至不可能出现数组!


2、

(1)、形参与实参之间的关系

A、个数一致;

B、按位置关系必须对应;

C、数据类型必须一致;

D、值传递


将实参表达式的值,复制一份,赋值给形参变量!


(2)、私有变量

在一个函数的函数体中定义的变量,以及该函数的所有形参变量,都是这个函数的私有变量。

一个函数只能使用、调用这个函数的私有变量和“公有变量”,绝对不能直接使用其它函数的私有变量(包括数组)。

私有变量是在定义这个变量的函数被调用时,才申请存储空间;私有变量(尤其是形参变量)的空间,与其它函数的私有变量的空间,是没有任何关系的,即,其空间是独立申请的。

私有变量将随着定义它的函数的运行结束,而释放其空间。


(3)、形参不能修改实参的值

被调函数对形参变量所进行的任何修改,绝对不会更改与其对应的实参的值,这就是“值传递”的必然结果!!!

对形参变量所进行的任何修改,绝对不会更改实参表达式的值 !

C 语言中,“指针”存在的理由:

最核心的原因:C 语言是一个函数语言,没有过程这个概念,就需要指针传变量的地址,才能对变量进行修改!


函数特点


1、

C 语言函数的重要特点

A、高度的独立性:任何函数只能引用属于自己的私有变量和全局变量,绝对不能直接引用其它函数的私有变量;这意味着,不能在被调函数中,直接修改主调函数的私有变量的值;

B、函数返回值最多只有一个,若需要通过被调函数同时得到多个结果,那是行不通的;

C、函数的参数(实参与形参)的关系,在 C 语言函数中,只有一种:值传递(传递的是值,只不过这个值可能是普通的值,也可能是地址值),且这种传递方式所产生的必然结果是:对被调函数的形参变量所进行的任何更改,绝对不会影响主调函数的实参的值!

上述三个特点,将对 C 语言函数的功能产生巨大的束缚:在上述情况存在的前提下,C 函数是无法实现:“同时更改主调函数中多个私有变量的值”的功能!


2、

指针的概念,就是为了解决上述 C 语言“致命”问题而提出来的!

指针解决上述问题的具体方法:

A、将需要更改的变量(空间)的首地址作为实参;

B、被调函数对应的形参变量必须是上述变量的指针类型进行接收,这将使被调函数的形参变量“指向”主调函数中,需要更改的那个变量;

C、在被调函数中,通过 * (指向)运算,间接地修改主调函数相关变量的值。

1void fun (int *);

2void fun (int *num) {

3    *num = 5;  //通过指针修改 a 空间的值,进行了指向运算

4}

5

6int main (void) {

7    int a = 6;

8

9    fun(&a);  //传的是 a 空间的地址

10    printf("%d\n", a)  //输出的结果是 5

11}


变量生命域与作用域


1、

全局变量与局部变量

(1)、全局变量的定义是在 {} 之外进行的;在 {} 之内定义的变量和所有的形参变量都是局部变量;

(2)、全局变量能被那些在书写顺序上,其后定义的函数所引用;局部变量只能被定义它的函数所引用;

(3)、全局变量的空间是在主函数运行之前申请的,且在主函数运行结束后(即,整个程序运行完毕后)才释放空间的;局部变量是在定义它的函数被调用时才申请空间,且随着函数运行结束而释放空间;

(4)、全局变量在定义后赋值前,其值由 C 语言强制赋值为 0;局部变量在定义后赋值前,其值为垃圾;

(5)、全局变量的使用,可使程序设计变得方便,但这种方便会带来函数之间“耦合”程度的增加,不利于大中型软件开发,不利于团队开发,也不利于软件的维护;全局变量的使用必须谨慎,这是《软件工程》思想所推荐的。


2、

变量存储类型

自动存储类:auto (可缺省)int a; <=> auto signed int

静态存储类:static

寄存器存储类:register

外部存储类:extern


(1)、自动存储类变量和静态存储类变量的定义:

1int a;

2static int b;

(2)、静态存储类变量是在主函数运行前申请空间,且在整个程序运行结束后释放;自动存储类变量是在定义它的函数被调用时才申请空间,且在定义它的函数运行结束后,释放其空间;

(3)、静态存储类变量在定义后未赋值前,其值被 C 语言强行赋值为 0;自动存储类变量在定义后未赋值前,其值为垃圾值;

(4)、静态存储类变量,如果是局部变量,则只能被定义它的函数所引用;

(5)、若某函数被多次调用,且该函数定义有静态存储类变量;则,在调用该函数结束后,它所定义的自动存储类变量的空间都被释放,而静态存储类变量的空间是不释放的;在下一次该函数被调用时,静态存储类空间的值是在上一次调用结束的基础上进行再一次引用的,因此,静态存储类变量具有“累加”效应。


函数遗留问题


一维数组名称作为实参、二维数组名称作为实参,形参该以何种数据类型接收的呢?又怎么使用呢?

函数的递归调用,也就是常见的递归算法有哪些条件呢?递归又该如何实现?有哪些应该的场景需要递归呢?

在操作系统底层源码中好多写法就是函数指针,指向函数的指针,那么指针函数和函数指针又该怎么理解呢?怎么使用呢?

针对这些遗留问题,有兴趣的可以自己先去思考、去学习,去研究,我在写 C 进阶之旅的时候,都会写到。

本篇文章仅仅是把 C 语言的函数带入门,以及说明了为什么要有指针,指针的出现就是为了函数中的传参,学习 C 语言之旅,路还很长,琢磨透彻,在敲代码实现,总会有进步的!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,424评论 3 44
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,323评论 0 2
  • 1.C和C++的区别?C++的特性?面向对象编程的好处? 答:c++在c的基础上增添类,C是一个结构化语言,它的重...
    杰伦哎呦哎呦阅读 9,478评论 0 45
  • 1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧...
    金巴多阅读 1,729评论 0 9
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,588评论 1 19