C语言函数

函数:function,功能模块

C语言中,函数是完成某个特定功能的指定序列的封装。(在C语言中,指令只能在函数内部)

函数可以实现代码的复用,以及模块化的设计

结构化设计主张把大任务,分成多个小任务(多个函数)来完成

函数就是实现某个功能的指令序列

设计一个函数,需要考虑哪些问题?

1)这个函数的功能是什么?

目的

2)完成这个功能,需要什么资源?输入参数

需求分析

3)怎么完成?  

算法思路

4)完成情况,结果?

返回值

输出

功能:求一个数组的最大值

1)目的:求一个数组的最大值

2)需要的资源

整个数组

3)算法思路

遍历

4)返回值

1.c函数实现

C语言定义一个函数

返回值类型 函数名(输入参数列表)

{

声明部分

语句部分 =》指令序列

}

“返回值类型” :函数返回值的类型

“函数返回值” :语句return 后面的那个表达式的值

函数也可以没有返回值,即返回值类型为void

return ; =>仅仅结束该函数

return ; =>该函数有返回值

“函数名”:要符合C语言的标识符的规定

“输入参数列表” :功能模块的输入

格式如下:

(参数类型1 参数名1,参数类型2 参数名2,......)

参数就是函数的局部变量,只不过他的初始值有调用者给定

函数也可以没有参数,即输入参数列表为空或void

{} :花括号里面就是完成这个函数的功能的代码的实现

函数头+函数体

/*

求一个数组的最大值

*/

int find_max(int a[],int n)

{

int max = a[0];

int i;

for(i = 0;i < n;i++)

{

if(a[i] > max)

{

max = a[i];

}

}

return max;

}

这个函数里面的指令会不会自动执行?

2.函数调用:

调用函数 :执行某个函数

调用函数:

要调用的函数名(传递个这个函数的实际参数);

函数调用语句:要调用的函数名(传递个这个函数的实际参数);

要调用的函数名(传递个这个函数的实际参数) =》函数调用表达式

函数调用表达式的值,就是这个函数的返回值

函数的调用过程: “传值调用”

把实际参数的值赋值给对应的形式参数,然后跳到被调用的函数中去执行

,被调用函数return语句表名被执行完毕,并且整个函数调用表达式的值

就是return后面的表达式的值

实际参数:函数调用表达式里面的参数。实际参数不需要写类型

所有有值的表达式都可以当做实际参数

fun(3,4+5);//3,4+5.0称为实参

int a = 3,b = 7;

fun(a,a+b);

形式参数:函数定义时的参数

int fun(int a,int b) //a,b就是形参

{

}

练习:

1)写一个函数,判断一个数组是否为递增数组

返回1

不是 返回0

/*

判断一个数组是否为递增数组

@a:数组名

@n:数组元素的个数

返回值:

1 =》递增

0 =》非递增

*/

int is_inc(int a[],int n)

{

int i;

for(i = 0;i < n-1;i++)

{

if(a[i] >= a[i+1])

{

return 0;

}

}

return 1;

}

函数调用过程:

传值调用,把实参的值拷贝一份赋值给相应的形参

主调函数: 调用别人的函数

被调函数: 被别人调用的函数

数据传递

主调函数 -》被调函数   参数

被调函数 -》主调函数   返回值

主调函数 -》被调函数   全局变量

3.递归函数

我们在定义一个函数表达式的时候,有直接或间接的调用了该函数表达式本身

这种函数称为递归函数

假设f(n)n的阶乘

f(4) =>4!

f(5) =>5!

...

f(n) =>n!

when n = 0 or n = 1 f(n) == 1

when n >= 2  f(n) = f(n-1)*n

=>f(n) 为递归函数

C语言直接支持函数的递归调用(不能是无限递归)

当递归到某个程度是,其结果显而易见

int f(int n)

{

if(n < 0)

{

}

if(n == 0 || n == 1)

{

return 1;

}

else

{

return n*f(n-1);

}

}

int main()

{

int n = 3;

}

====

设计递归

1)在解决问题的时候,遇到了该问题同样的问题

2)不能是无限递归

练习:

(1)写一个函数,求斐波那契数列的第n

1 1 2 3 5 8 13 .....

n = 1 F(1) == 1

n = 2 F(2) == 1

n = 3 F(3) == F(2) +F(1)

int F(n)

{

if(n <= 0 )

{

return 0;

}

if(n == 1 || n == 2)

{

return 1;

}

else

{

return F(n-1)+F(n-2);

}

}

(2)hanoi塔问题

写一个函数,实现Hanoi塔的搬运步骤

功能:把n个盘子从A移动到C,中间利用B

输入参数:

n :多少个盘子

A :起点

B :中转点

C :终点

Hanoi(1,A,B,C) ?

直接从A移动到C

Hanoi(2,A,B,C)

A->B

A->C

B->C

//Hanoi(3,A,B,C)

Hanoi(n,A,B,C)

 n > 1

(1) Hanoi(n-1,A,C,B)

(2)A->C

(3)Hanoi(n-1,B,A,C)

void Hanoi(int n,char A,char B,char C)

{

if(n == 1)

{

printf("%c->%c ",A,C);

return ;

}

Hanoi(n-1,A,C,B);

printf("%c->%c ",A,C);

Hanoi(n-1,B,A,C);

}

作业:

(1)能不能计算移动n个盘子,所需要的步数

(2)“鞍点”:行中最大,列中最小

a[4][4]

#include <stdio.h>

int main()

{

int a[4][4],i,j,k,max;

for(i = 0;i < 4;i++)

{

for(j = 0;j < 4;j++)

{

scanf("%d",&a[i][j]);

}

}

for(i= 0;i<4;i++)//

{

max = a[i][0];

for(j = 0;j < 4;j++)//找到一行中最大的那个值

{

if(max < a[i][j])

{

max = a[i][j];

}

}

for(j = 0;j < 4;j++)//找最大的值的位置

{

if(max == a[i][j])

{

for(k = 0;k < 4;k++)

{

if(a[k][j] < a[i][j])

{

goto loop;

}

}

printf("鞍点:a[%d][%d] = %d ",i,j,a[i][j]);

}

loop:

  ;

}

}

}

=======================

C语言对象的作用域和生存期

1.作用域

what

起作用的一个区域

变量和函数的作用域

变量从作用域来分,分两种

1)全局变量:定义在函数外面的变量

整个工程都起作用的全局变量

一个有多个源文件(1.c,2.c,3.c....

在这些文件中都可以访问的全局变量

eg:

1.c

int a = 5;(函数外部定义)

作用域:整个工程文件

2.c需要用到1.ca

extern int a;//这个变量a是在外面的文件定义的,但是当前文件需要用到

仅在当前文件内起作用的全局变量

1.c  

static  int a = 5;(函数外部定义)

=>声明a仅在本文件(1.c)中有效,其他文件不能用1.ca

2)局部变量

定义在{}(函数内部或代码块)里面的变量,局部变量

作用域:仅在{}(函数内部或代码块)内起作用

eg:1.c

int a = 250;

int main()

{

int a = 5;

if(1)

{

int a = 6;

printf("A = %d ",a);

}

printf("a = %d ",a);

}

A = 6

a = 5

只要作用域不一样就可以定义同名的变量

====

函数的作用域

1)全局作用域

对整个工程都有效

1.c

int sum(int a,int b)

{

return a+b;

}

2.c

声明:sum是一个外部定义的函数

extern  int sum(int a,int b);

fun()

{

sum(2,3);

}

2)仅在文件中有效

1.c

static int sum(int a,int b)

{

return a+b;

}

=>sum仅在当前文件有效

=static的两个作用

1static修饰全局变量和函数时,使得全局变量和函数的作用域只在当前文件有效

 

(2)static修饰局部变量,使得局部变量的生存期变为随着进程的持续性并且static修饰的变量,只被初始值赋值一次,之后不会再被循环中比如while(1){

Static int x = 2,

X++;}此时只会赋值一次,第二次进循环将不再被赋值为2,而是直接处理下面的内容

2.生存期

what

从生到死的期间

随文件系统的持续性:

随内核持续性:

操作系统一启动他就存在,并且存在到操作系统关闭

随进程的持续性(随程序的持续性):

程序一运行他就存在,并且存在到程序的退出

int a = 5;

void fun()

{

int c;

static int b = 6;

b++;

printf("b = %d ",b);

}

int main()

{

fun();

fun();

}

全部变量astatic局部变量,随进程的持续性

程序一运行就会给a,b开辟空间,并且这个空间会一致存在直到程序退出

 

static局部变量定义并赋值的语句,只会在给该变量分配空间的时候执行一次

 

其他的普通局部变量:函数执行时分配空间,执行完毕,释放空间

 

 

随代码块持续性:

这个代码运行就存在,直到代码结束

 

普通的局部变量

 

原文地址:https://www.cnblogs.com/qihuanye-229110/p/11147360.html