标签:组成 core 不能 编写 void 函数类型 根据 最小数 重叠
一、概述
1、函数的概念(c程序的结构)
(1)一个C程序可以分为若干个函数
(2)每个程序有且只能有一个主函数(main),其他函数都是“子函数”
(3)子函数可以互相调用,但主函数不能被调用
(4)一个C源程序由一个或多个文件构成,一个源程序文件是一个编译单位
2、说明
(1)c程序的执行从main函数开始,调用其他函数后人回到main函数,程序在main函数结束时结束
(2)所有子函数都是平行的,任何子函数都不属于其他函数
(3)从用户的角度看,函数可分为:标准函数,即库函数;自定义函数
(4)从函数形式看,可分为:
无参数函数:主调函数无数据传送给被调函数,可带或不带返回值。如:printstar();
有参数函数:主调函数与被调函数间有参数传递,主调函数可将实参传送给被调函数的形参, 被调函数的数据可返回主调函数。如:printf()。
#include <stdio.h> void main( ) {void printstar( ); void print_message( ); printstar( ); print_message( ); printstar( ); } void printstar( ) {printf (“***********************\ n” ); } void print_message( ) {printf (“_ _ _ _ _How_do_you_do!\n”) ;} /* 运行结果: **************************** How do you do! **************************** */
二、函数的定义
1、函数定义的一般形式:
类型说明 函数名 ([形式参数说明])
{ 函数体 } ——>{ [ 局部变量说明 ] ——> 局部变量:函数体内定义的变量,其有效范围仅限于所在函数的内部,离开函数体则无意义。
语句
}
形式参数说明方法:类型说明 变量名 [, 类型说明 变量名 ]……
【1】无参函数的定义形式
类型说明 函数名 ()
{ 函数体 }
【2】有参函数的定义形式
类型说明 函数名 (形式参数说明)
{ 函数体 }
【3】空函数的定义形式
类型说明 函数名 ([形式参数说明])
{ }
三、函数参数和函数的值
一个C程序由若干个函数组成,各函数调用时经常需要传递一些数据。即调用函数把数据传递给被调用函数,经被调用函数处理后,得到一个确定的结果,在返回调用函数时,把这个结果带回调用函数。各函数间的信息的往来是有参数传递和返回语句实现的。
(1)形式参数和实际参数
函数参数:用于函数间数据的传递
形式参数:定义函数时使用的参数(函数名后面括号中的变量名)
实际参数:调用函数时使用的参数(函数名后面括号中的表达式)
说明:
【1】定义参数时,必须说明形参的类型。形参只能是变量或数组。
【2】函数被调用前,形参不占用内存;函数调用结束后,形参所占用的内存也将被回收。
【3】实参可以是常量、变量或表达式。
【4】实参与形参的类型必须一致。字符型和整型可以互相匹配。
【5】C语言中实参对形参的数据传递是“值传递”,即单向传递。它仅由参数的对应位置确定,与名字无关。
(2)函数的返回值
【1】返回函数值的方法
函数的返回值也就是函数值,是一个确定的值
1)> 如果一个函数有返回值,就必须使用return语句。
2)> 一个函数中可以有一个以上的return语句,但不论执行到哪个return都将结束函数的调用返回主调用函数
3)> return语句中的括号可以省略;return后面的值可以是一个表达式。
【2】函数值的类型
1)>函数的类型即函数值的类型,如函数是 int 型,函数值也是 int 型。
2)>省略了类型说明的函数是 int 型的。
3)>return 用中表达式的值一般应与函数类型一致。
4)>如果不一致,则需要进行类型转换。只有数值型的数据可以进行自动类型转换,以函数类型为准。
【3】不需要返回值的函数
1)>如果函数中没有使用 return 语句,函数返回值是一个不确定的数值。
2)>如果一个函数不需要返回值(表示一个过程),可以用 void 做类型说明。
3)>如果一个函数被声明为 void 类型,就不允许再引用它的返回值(即只能用函数语句形式调用)。
四、函数的调用
1、函数调用的一般形式
一般形式: 函数名(实参列表)
说明:
(1)如果调用无参函数,实参列表可以忽略,但括号不能省。
(2)实参的各数和形参一般相等。
(3)实参与形参的类型应一 一对应,必要时使用类型转换。
注意:不同系统中,实参的计算顺序不同。微机上一般是从右到左。为避免由此引起的混乱,一般应在调用函数前计算出实参的值。
2、函数的调用方式
(1)函数语句
形式:函数名 (实参列表);
以独立的语句去调用函数。不要求有返回值,仅完成一定的操作。
例 printstar(); printf(“Hello,World!\n”);
(2)函数表达式
函数返回一个确定值,以参加表达式的运算。不可用于void
例 m=max(a,b)*2;
(3)函数参数
函数调用作为另一个函数的参数。
例 printf(“%d”,max(a,b)); /*输出大数*/
m=max(a,max(b,c)); /*三数比大小*/
3、函数调用的执行过程
【1】按从右向左的顺序,计算实参中各表达式的值
【2】按照位置,将实参的值一一对应的传送给形参
【3】执行被调用函数
【4】当遇到 return(表达式)语句时,计算表达式的值,并返回主调函数
4、函数的原形说明(函数声明)
C语言中函数声明称为函数原型(形)。函数定义与函数声明不同,声明只与函数定义的第一行相同。声明可以不写形参名,只写形参类型。
函数说明位置:程序的数据说明部分(函数内或外)
作用:告诉编译系统函数类型、参数个数及类型,以便检验
在程序中调用函数需满足以下条件:
(1)被调用函数必须存在,且遵循“先定义后使用”的原则。
(2)如果被调用函数的定义在主调函数之后(位置),可以先给出原形说明。
原形说明的形式:类型说明 函数名(参数类型,参数类型,……);
其他说明:
库函数的原形说明存放在头文件(.h)中,通过使用 include 预处理命令将这些原形说明插入程序中。
旧版本C中函数声明不采用函数原型,只声明函数名和函数类型。如: float add( )
函数调用之前,如果未对函数作声明,则编译系统把第一次遇到的函数形式作为函数声明,并默认为int型。即:函数类型是 int 型可以不作函数声明,最好作声明。
被调用函数的定义(程序)在主调函数之前,可以不加函数声明。 在所有函数定义前,已在函数外部做了函数声明,则在各主调函数中可以不加函数声明。
五、函数的嵌套调用
函数调用是指在一个函数的函数体内有调用了其他函数。
#include <stdio.h> int fun1(int x,int y); void main(void) { int a,b; scanf(“%d%d”,&a,&b); printf(“The result is:%d\n”,fun1(a,b) ); } int fun1(int x,int y) { int fun2(int m); return ( fun2(x)+fun2(y) ); } int fun2(int m) { return (m*m); } /* 输入: 3 4 输出: The result is: 25 */
#include <stdio.h> int dif(int x,int y,int z); //函数声明 int max(int x,int y,int z); int min(int x,int y,int z); void main() { int a,b,c,d; scanf("%d%d%d",&a,&b,&c); d=dif(a,b,c); printf("Max-Min=%d\n",d); } int dif(int x,int y,int z) //求最大值与最小值差的函数 } return max(x,y,z)-min(x,y,z); } int max(int x,int y,int z) //求最大值函数 { int r; r=x>y?x:y; return(r>z?r:z); } int min(int x,int y,int z) //求最小值函数 { int r; r=x<y?x:y; return(r<z?r:z); }
六、函数的递归调用
1、递归:在函数调用过程中,直接或间接的调用自身。
2、递归调用方式
【1】直接递归调用:在函数体内又调用自身
【2】间接递归调用:当函数1去调用另一函数2时,而另一函数2反过来又调用函数1自身。
注:解决无终止递归调用必须要确定好结束递归的条件。
3、例题
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int age(int n) { int c; if (n == 1) c = 10; else c = 2 + age(n - 1); return(c); } void main() { printf("%d\n", age(5)); system("pause"); }
有些问题,可以用递推,也可以用递归的方法解决。
递推:从一个已知的事实出发,按一定规律推出下一个事实,再从已知的新的事实,推出下一个新的事实。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { int i, s = 1; for (i = 1; i <= 5; i++) s = s* i; printf("s = %d\ n", s); system("pause"); }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { float fac(int n); int n; printf("Input a integer number:"); scanf("%d", &n); //y = fac(n); printf("%d! = %d", n, int(fac(n))); //注意:fac(n)为float类型,前面对应%f,若用%d,则后面要转成int型 system("pause"); } float fac(int n) { float f; if (n<0) printf("n<0,data error!"); else if (n == 0 || n == 1) f = 1 ; else f = (fac(n - 1)*n); return f; }
七、数组作为函数的参数
1、数组元素做函数实参
与变量做实参一样,数组元素做实参是“值传递”。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> float max(int x,int y) { return (x>y?x:y); } void main() { int a[10],i,m; printf("enter 10 integer:\n"); for (i = 0; i < 10; i++) scanf("%d", &a[i]); m = a[0]; for (i = 1; i < 10; i++) m = max(m, a[i]); printf("max is %d", m); system("pause"); }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { float average(float array[10]); float score[10], aver; int i; printf("Input 10 scores: \n"); for (i = 0; i<10; i++) scanf("%f", &score[i]); printf("\n"); aver = average(score); printf("Average is: %5.2f", aver); system("pause"); } float average(float array[10]) { int i; float aver, sum = array[0]; for (i = 1; i<10; i++) sum = sum + array[i]; aver = sum / 10; return (aver); }
2、一维数组与函数参数
若函数的形参是数组,对应的实参一定是数组名
说明:
【1】实参数组与形参数组的类型必须一致
【2】用数组名做参数时,传递的是数组的首地址,因此形参数组也可以不指定大小。但需另设一个参数,传递数组元素的个数。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int max(int x[10]) { int i, m; m = x[0]; for (i = 1; i < 10; i++) if(m < x[i]) m = x[i]; return m; } void main() { int a[10], i; printf("enter 10 integer:\n"); for (i = 0; i < 10; i++) scanf("%d", &a[i]); printf("max is %d", max(a)); system("pause"); }
#include <stdio.h> #include <stdlib.h> void main() { float average(float array[], int n); float score_1[5] = { 98.5, 97, 91.5, 60, 55 }; float score_2[10] = { 67.5, 89.5, 99, 69.5, 77, 89.5, 76.5, 54, 60, 99.5 }; printf("The average of clase A is %6.2f\n", average(score_1, 5)); printf("The average of clase B is %6.2f\n", average(score_2, 10)); system("pause"); } float average(float array[], int n) //另设一个参数,传递需要处理的数组元素个数 { int i; float aver, sum = array[0]; for (i = 1; i<n; i++) sum = sum + array[i]; aver = sum / n; return (aver); } /* 运行: The average of class A is 80.40 The average of class B is 78.20 */
【3】数组做函数参数时,形参数组和和实参数组共享同一个存储单元
如果形参数组的元素的值被修改,实参数组元素的值也就被修改了。
#include <stdio.h> #include <stdlib.h> void main() { void sort(int array[], int n); int a[10], i; printf("enter the array\n"); for (i = 0; i<10; i++) scanf("%d", &a[i]); sort(a, 10); printf("the sorted array: \n"); for (i = 0; i<10; i++) printf("%d ", a[i]); printf("\n"); system("pause"); } void sort(int array[], int n) { int i, j, k, t; for (i = 0; i < n - 1; i++) { k = i; for (j = i + 1; j < n; j++) if (array[j] < array[k]) k = j; t = array[i]; array[i] = array[k]; array[k] = t; } }
3、用多维数组名作函数参数
【1】多维数组可以作为函数的参数
【2】如果形参是多维数组,可以省略第一维的大小,但不能省略其他维的大小。
#include <stdlib.h> #include <stdio.h> void main() { int max_value(int array[][4]); int a[3][4] = { { 1, 3, 5, 7 }, { 2, 4, 6, 8 }, { 15, 17, 34, 12 } }; printf("max value is %d\n", max_value(a)); system("pause"); } int max_value(int array[3][4]) //多维形参数组第一维维数可省略, 第二维必须相同 { int i, j, max; max = array[0][0]; for (i = 0; i<3; i++) for (j = 0; j<4; j++) if (array[i][j]>max) max = array[i][j]; return max; }
八、局部变量与全局变量
1、局部变量
什么是局部变量?(内部变量)
【1】在一个函数内部定义的变量
【2】函数的形式参数
【3】在某个复合语句中定义的变量
说明:
【1】局部变量只在自己的范围内有效
【2】如果局部变量的有效范围有重叠,则有效范围小的优先
【3】不同函数中同名变量,占不同内存单元
2、全局变量
在函数之外定义的变量(外部变量)是全局变量
有效范围:从定义变量的位置开始到原文件结束
说明:(习惯上,全局变量名的第一个字母用大写 )
【1】利用全局变量可以在函数间传递数据,使用全局变量可以减少函数的实参和形参个数。
#include <stdio.h> #include <stdlib.h> float max = 0, min = 0; float average(float score[], int n) { int i; float sum = score[0]; max = min = score[0]; for (i = 0; i < n; i++) { sum = sum + score[i]; if (max < score[i]) max = score[i]; if (min > score[i]) min = score[i]; } return sum / n; } void main() { float avg, score[10]; int i; for (i = 0; i < 10; i++) scanf("%f", &score[i]); avg = average(score, 10); printf("max:%f min:%f average:%f\n", max, min, avg); system("pause"); }
【2】应尽量少使用全局变量
1)>全局变量在程序执行的全过程都占用存储单元。
2)>不利于程序的移植。程序的可读性变差。
【3】如果全局变量与局部变量同名,则局部变量优先
#include <stdlib.h> #include <stdio.h> int a = 3, b = 5; void main() { int max(int a, int b); int a = 8; // 局部变量a=8将外部变量a=3屏蔽 printf("max=%d\n", max(a, b)); system("pause"); } int max(int a, int b) { int c; c = a>b ? a : b; return(c); } //运行结果:max=8
九、变量的存储类别
1、变量的动态存储和静态存储
全局变量与局部变量 ——> 变量的作用域
静态存储变量和动态存储变量 ——> 变量的存储类别,即生存期
【1】生存期:
静态变量:从程序开始执行到程序结束
动态变量:从包含该变量定义的函数开始执行至函数执行结束
【2】内存中供用户使用的存储空间包括:
1.程序区
2.静态存储区:程序运行期间(编译时)分配固定的存储空间。
3.动态存储区:程序运行期间(执行时)根据需要动态分配存储空间。
【3】变量或函数的属性:
存储类别:自动型 auto
静态型 static
寄存器型 register
外部型 extern
2、局部变量的存储类别
【1】自动变量 —— 存储在动态存储区,用 auto 说明
函数内部无static声明的局部变量均为动态存储类别,被分配在动态区 。
存储类别为自动时,声明符auto可省;自动变量被 分配在动态区,未赋初值时,其值未定义,每次调用重新赋值。
例如:
int f(int a) /*定义f函数,a为形参*/ {auto int b,c=3; /*定义b、c为自动变量*/ … } 又如:
auto int b,c=3; int b,c=3; /*两者等价*/
【2】局部静态变量 —— 占用静态存储区,用 static 说明
若希望函数调用结束后,局部变量的值保留,则指定该变量为静态局部变量,用static对变量加以声明。
#include <stdlib.h> #include <stdio.h> void main() { void increment(void); increment(); increment(); increment(); system("pause"); } void increment(void) { int x = 0; //结果:1 1 1 //static int x = 0; //结果:1 2 3 x++; printf("%d\n", x); }
#include <stdlib.h> #include <stdio.h> void main() { int f(int); int a = 2, i; for (i = 0; i<3; i++) printf(" %d ", f(a)); //结果:7 8 9 system("pause"); } int f(int a) { auto b = 0; static int c = 3; b = b + 1; c = c + 1; return(a + b + c); }
说明:
1)>局部静态变量属于静态存储类别。在程序整个运行期间都不释放存储空间,程序运行结束后才释放存储单元。
2)>局部静态变量在编译时赋初值(仅赋一次值),前次结果保留。
3)>如果局部动态变量若未赋初值,其值不确定;局部静态变量时没有赋初值,编译时会自动赋初值,其值为0或‘\0’(字符变量)。
4)>局部静态变量只能在定义它的函数内被引用(调用结束后存在但不能被其他函数使用)。
使用局部静态变量的场合
1)>需要保留上一次调用结束时的值
#include <stdlib.h> #include <stdio.h> void main() { int fac(int n); int i; for (i = 1; i <= 5; i++) printf("%d != %d\n", i, fac(i)); system("pause"); } int fac(int n) { static int f = 1; f = f*n; return(f); } /* 运行结果: 1 != 1 2 != 2 3 != 6 4 != 24 5 != 120 */
2)>初始化后变量只被引用而不改变其值,则用静态局部变量较方便,以免每次调用时重新赋值,但会一直占用内存浪费系统资源。
【3】寄存器变量 —— 占用动态存储区,用 register 说明
CPU内有寄存器可用来存放数据,若把数据声明为寄存器类型,则将该类型的数据存放在寄存器中,其优点是:减少数据与内存之间的交换频率,提高程序的效率和速度。
寄存器类型变量的几点说明:
1. 寄存器变量对寄存器的占用是动态的,局部自动变量类型和形参可定义为寄存器变量,局部静态变量不能定义为寄存器变量。
2.计算机的寄存器的个数有限, 不同C系统对寄存器的使用个数,对register变量的处理方法不同,对寄存器变量的数据类型有限制。
3.有的系统将寄存器变量转化为自动变量处理,而有的系统会自动设置寄存器变量。
4. long,double,float不能设为register型,因为超过寄存器长度。
3、全局变量的存储类别
【1】全局变量都是静态的
【2】用 extern 说明一个在其他原文件中定义的全局变量
外部变量也称全局变量,在函数外部定义,其作用域是从变量的定义处开始,到本程序文件的未尾。在定义的作用域内,全局变量可为程序中各个函数所引用。 可以用extern声明外部变量,以扩展外部变量的作用域。
一个文件内声明外部变量 外部变量没在文件开头定义,其作用域为定义处到文件结束。定义处之前的函数要使用,则在引用前用关键字extern作“外部变量声明”。
#include <stdio.h> #include <stdlib.h> int max(int x, int y) { int z; z = x>y ? x : y; return(z); } void main() { extern int A, B; //可以省略为:extern A,B; printf(" %d ", max(A, B)); //结果:13 system("pause"); } int A = 13, B = -8;
#include <stdio.h> #include <stdlib.h> void main() { void gx(), gy(); extern int X, Y; printf("1: x = %d\ty = %d\n", X, Y); Y = 246; gx(); gy(); system("pause"); } void gx() { extern int X, Y; X = 135; printf("2: x = %d\ty = %d\n", X, Y); } int X, Y; void gy() { printf("3: x = %d\ty = %d\n", X, Y); } //1 : x = 0 y = 0 //2 : x = 135 y = 246 //3 : x = 135 y = 246
在多文件的程序中声明外部变量 如果一个程序由多个文件组成,而一个外部变量需要在几个文件中引用,此时,可以在任一文件中定义该外部变量,在其它文件中用extern加以声明 若在每个文件中都定义该外部变量,则系统将提示“重定义类型错”。
#include <stdlib.h> #include <stdio.h> /*文件file1.c*/ int A; void main() { int power(int); int b = 3, c, d, m; printf("Enter the number a and its power m:\n"); scanf("%d %d", &A, &m); c = A*b; printf("%d*%d=%d\n", A, b, c); d = power(m); printf("%d**%d=%d", A, m, d); system("pause"); } /*文件file2.c*/ extern int A; int power(int n) { int i, y = 1; for (i = 1; i <= n; i++) y *= A; return(y); } /* 输入:a=5,m=2 结果:5*3=15 5**2=25 */
【3】用 static 说明一个不能在其他原文件中定义引用的全局变量
如果外部变量只允许本文件使用,不允许其它文件引用,则定义时加static声明。称为“静态外部变量” 只在工程方法中有效,在文件包含中则不起作用 常用于多人编同一程序,又使用同名变量时 加或不加static声明的外部变量都是静态存储,但其作用域不同
关于变量的声明和定义
函数:由“声明部分”和“执行语句”组成
声明部分: 对有关的标识符(变量,函数,结构体)的属性进行说明,对于函数,声明和定义区别明显,声明是函数原型,定义是函数本身,是一个独立的程序模块;
变量的声明有两种情况 定义性声明:需建立存储空间,如int a;也称定义。 引用性声明:不建立存储空间,如extern A 外部变量“定义性声明”只能一次,“引用性声明”多次。
广义地讲,声明包括定义,但并非所有的声明都是定义;
如:int A;既包含声明又包含定义; extern A;只是声明,而无定义。
约定:建立存储空间的声明称定义; 不建立存储空间的声明称声明。
Static定义性声明变量作用二个:
局部变量用static定义性声明,分配的存储空间在程序执行期间始终存在,但作用域 只限定义它的函数或分程序。
全局变量用static定义性声明,变量的作用域仅限本文件模块
Auto,register,static是在定义变量的基础上加上这些关键字,不能单独作用。
注:应尽量少用全局变量
4、存储类别小节
【1】变量的定义方法: [ 存储类别 ] 数据类型 变量名 ,……
【2】变量的划分
按作用域:局部变量 —— 自动变量;静态局部变量;寄存器变量;形式参数。
全局变量
按生存期:动态存储 —— 自动变量;寄存器变量;形式参数。
静态存储 —— 静态局部变量;全局变量。
按变量的存放位置:动态存储区 —— 自动变量;形式参数。
静态存储区 —— 静态局部变量;全局变量
寄存器 —— 寄存器变量
//方法二:全局变量 #include <stdio.h> #include <stdlib.h> int x, y; void swap(void) { int t; t = x; x = y; y = t; } void main() { scanf("%d %d", &x,&y); swap(); printf("a=%d b=%d\n", x, y); system("pause"); } //方法三:数组 #include <stdio.h> #include <stdlib.h> void swap(int x[2]) { int t; t = x[0]; x[0] = x[1]; x[1] = t; } void main() { int x[2]; scanf("%d %d", &x[0], &x[1]); swap(x); printf("a=%d b=%d\n", x[0], x[1]); system("pause"); }
标签:组成 core 不能 编写 void 函数类型 根据 最小数 重叠
原文地址:https://www.cnblogs.com/dabj-yb/p/12589417.html