前言:
今天看官们对“c语言中输出函数”大约比较着重,同学们都想要剖析一些“c语言中输出函数”的相关知识。那么小编在网摘上搜集了一些有关“c语言中输出函数””的相关知识,希望大家能喜欢,小伙伴们一起来学习一下吧!1.了解函数
什么是函数
函数就是 C 语言的模块,一块一块的,有较强的独立性,可以相互调用,换句话说,C 语言中,一个函数里面可以调用 n 个函数,即大函数调用小函数,小函数又调用“小小”函数。这就是结构化程序设计,所以面向过程的语言又叫结构化语言。函数就是一系列 C 语句的集合,能完成某个特定的功能。需要该功能的时候直接调用该函数即可,不用每次都堆叠代码。需要修改该功能时,也只需要修改和维护这一个函数即可。
为什么需要函数
将语句集合成函数的好处是方便代码重用。所谓“重用”,是指有一些代码的功能是相同的,操作是一样的,只不过针对的数据不一样,这时就可以将这种功能写成一个函数模块,以后用到这个功能时只需要调用这个函数模块就可以了,不需要再重复地编写同样的代码。这样可以解决大量同类型的问题,避免重复性操作。将语句集合成函数方便代码的维护。哪个功能出问题了,或者需要修改某个功能,那就只需要修改某个功能的函数就可以了。
return_type function_name( parameter list ){ body of the function}**返回类型:**一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。**函数名称:**这是函数的实际名称。函数名和参数列表一起构成了函数签名。**参数:**参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。**函数主体:**函数主体包含一组定义函数执行任务的语句。
#include<stdio.h>int add(x, y);void main() { int x, y; scanf_s("%d,%d", &x, &y); int sum = add(x, y); printf("%d", sum);}int add(int x, int y) { return x + y;}
计算球体面积与体积
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdlib.h>const double PI = 3.1415;double Area(int r) { return 4 * PI * r * r;}double Volume(int r) { return 4 / 3 * PI * r * r * r;}void main() { printf("地球面积:%f\n", Area(6371)); printf("地球体积:%f", Volume(6371));}
注:解决了代码重用
无参函数
通常用来执行一些功能比较固定单一的语句。
有参函数
通常通过处理传递过来的参数,将函数值返回给调用处。
写一个按键功能
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdlib.h>#include<Windows.h>void main() { //按下WIN键 keybd_event(VK_LWIN, 0, 0, 0); keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);}
库函数
由C语言系统提供用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数定义的头文件
自定义函数
用户在程序中根据需要而编写的函数;
常用库函数
标准头名
功能
描述
<assert.h>
诊断
仅包含assert宏。可以在程序中使用该宏来诊断程序状态(例如某个变量是否为0等),若检查失败,程序终止。
<ctype.h>
字符处理
包含判断字符类型及大小写转换的函数。
<errno.h>
错误监测
提供了errno。可以在调用特定库函数后检测errno的值以判断调用过程中是否有错误发生。
<float.h>
浮点数特性
提供了描述浮点数特性的宏。
<limits.h>
整型特性
提供了描述整数类型和字符类型特性的宏。
<locale.h>
本地化
提供了一些支持程序国际化的函数。
<math.h>
数学计算
提供了大量用以数学计算的函数。
<setjmp.h>
非本地跳转
提供了用于绕过正常的函数返回机制,从一个函数跳转到另一个正在活动的函数的setjmp和longjmp函数。
<signal.h>
信号处理
提供了包括中断和运行时错误在内的异常情况处理函数。
<stdarg.h>
不定参数
提供了支持函数处理不变个数的参数的工具。
<stddef.h>
常用定义
提供了常用的类型和宏。
<stdio.h>
输入输出
提供了大量输入输出函数。
<stdlib.h>
常用实用函数
提供了大量实用的函数。
<string.h>
字符串处理
提供了大量字符串处理函数。
<time.h>
日期和时间
提供了获取、操纵和处理日期的函数。
注意顺序
void hi();void main() { hi();}void hi() { printf("HI...");}
默认返回int
hi() { printf("HI..."); return 0;}
创建一个.h头文件
#include<stdio.h>void Hi() { printf("Hi...");}
载入自定义头
#include "hi.h"void main() { Hi();}
一个约束
头文件只放申明,实体放到c文件中
.h文件
#include<stdio.h>void Hi();
.c文件
#include "hi.h"void Hi() { printf("HI....");}
main调用
#include "hi.h"void main() { Hi();}2.函数的调用
函数间通过参数来传递数据,即通过主调函数中的实际参数(实参)向被调用函数中的形式参数(形参)进行传递。
实参向形参传递数据的方式:实参将值单向传递给形参,形参的变化不影响实参值。
#include<stdio.h>#include<stdlib.h>int main() { int a, b; void swap(int a, int b); scanf_s("%d,%d", &a, &b); swap(a, b); printf("main:a=%d,b=%d\n", a, b); system("pause"); return 0;}void swap(int a, int b) { int t; t = a; a = b; b = t; printf("swap:a=%d,b=%d\n", a, b);}
在main中,a,b的值没有交换。
形参交换了数据,而实参保持原数据不变。这是单向的值传递,所以形参的值改变后而实参的值没有改变。形参在函数中是变量名,在函数调用时,形参被临时分配相应的内存,调用结束后,形参单元被释放,而实参单元保留并维持原值。实参是表达式,负责向对应的形参标识的内存单元传递数据,实参向形参的数据传递是“值传递”。 实参与形参必须个数相同对应的形参和实参的类型必须一致
传入指针
形参为指向实参地址的指针,当对形参的指向操作时,就相当于操作实参本身。
#include<stdio.h>#include<stdlib.h>int main() { int a, b; void swap(int *a, int *b); scanf_s("%d,%d", &a, &b); swap(&a, &b); printf("main:a=%d,b=%d,&a=%p,&b=%p\n",a, b,&a,&b); system("pause"); return 0;}void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; printf("swap:a=%d,b=%d,&a=%p,&b=%p\n", *a, *b, a, b);}
函数嵌套
#include<stdio.h>#include<stdlib.h>void Run();void Do();void Go();int main() { Run(); system("pause"); return 0;}void Run() { printf("Run start...\n"); Do(); printf("Run end...\n");}void Do() { printf("Do start...\n"); Go(); printf("Do end...\n");}void Go() { printf("Go...\n");}
注:这个调用是套娃试调用,每进入一个子函数,都得先将子函数执行完毕再回到父函数。
带返回函数
#include<stdio.h>#include<stdlib.h>int add(int x, int y);void main() { int x = add(10, 20);//int x = add(add(10, 20), 100); printf("%d\n", x); system("pause");}int add(int x, int y) { return x + y;}
参数顺序
void add(int x, int y) { printf("x=%d,y=%d", x, y);}void main() { int x = 100; add(x, ++x);//这里是先计算表达式,再调用函数}
void add(int x, int y,int z) { printf("x=%d,y=%d,z=%d", x, y,z);}void main() { int x = 100; add(x, ++x,--x);//这里是先计算表达式,再调用函数,从右向左计算}3.可变参数
可变参数的函数必须至少有一个强制参数,可选参数的类型可以变化。可选参数的数量由强制参数的值决定,或由用来定义可选参数列表的特殊值决定。
对于每一个强制参数来说,函数头部都会显示一个适当的参数,像普通函数声明一样。参数列表的格式是强制性参数在前,后面跟着一个逗号和省略号(…),这个省略号代表可选参数。
语法:
type funcName(paramType1 param1, ...){ // 执行语句... return val}
#include<stdio.h>#include<stdlib.h>#include<stdarg.h>int add(int x,...);//可变参数void main() { int x = add(5,1,2,3,4,5); printf("%d\n", x); system("pause");}int add(int x,...) { va_list args;//创建一个char指针 va_start(args, x);//读取x个参数,把地址放到args中 int result = 0; for (int i= 0; i < x; i++) { result += va_arg(args, int);//逐一读取参数 } va_end(args);//清理va_list变量的内存 return result;}
使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏。具体步骤如下:
定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。使用宏 va_end 来清理赋予 va_list 变量的内存。
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<stdarg.h>#include<string.h>void printString(int x,...);//可变参数void main() { printString(5,"hi",",","this","is","test"); system("pause");}void printString(int x,...) { va_list args;//存地址 va_start(args, x); for (int i = 0; i < x; i++) { char str[50]; strcpy(str, va_arg(args, char*));//读取字符串到char[] printf("%s ", str); } va_end(args);}4.递归
函数的递归调用是指:一个函数在他的函数体内直接或间接地调用它自身。分为:直接递归(函数直接调用自身)和间接递归(函数通过其他函数调用自身)。可分为“回溯”和“递推”两个阶段。
一个简单例子
void run(int n) { printf("%d run...\n",n); if (n == 1) { return; } else { run(n - 1); }}void main() { run(5);}
阶乘递归
int fac(int n) { int f; if (n < 0) { return 0; } else if (n == 0 || n == 1) { f = 1; } else { f = n * fac(n - 1); } return f;}void main() { int n = 5; printf("%d", fac(n));}
斐波那契数列
int fib(int i) { if (i == 0) { return 0; } if (i == 1) { return 1; } return fib(i - 1) + fib(i - 2);}void main() { int i; for (int i = 0; i < 20; i++) { printf("%d\n", fib(i)); }}
递归的条件
每一个递归函数都应该只进行有限次的递归调用,否则它就会进入死胡同,永远也不能退出了,这样的程序是没有意义的。
要想让递归函数逐层进入再逐层退出,需要解决两个方面的问题:
存在限制条件,当符合这个条件时递归便不再继续。对于 factorial(),当形参 n 等于 0 或 1 时,递归就结束了。每次递归调用之后越来越接近这个限制条件。对于 factorial(),每次递归调用的实参为 n - 1,这会使得形参 n 的值逐渐减小,越来越趋近于 1 或 0。5.函数返回值生命周期
int add(int x, int y) { int z = x + y; printf("%p", &z); return z;}void main() { printf("%d", add(1, 2)); getchar();}
函数内部定义的变量,返回以后,变量就会被销毁
修改成全局变量
int z = 0;int add(int x, int y) { z = x + y; printf("%p", &z); return z;}void main() { printf("%d", add(1, 2)); getchar();}
这时会发现内存不会销毁。
int add(int x) { int z = 0; z = z + x; z = z + x; printf("%p", &z); return z;}void main() { printf("%d", add(3)); getchar();}
这里可以查看cpu寄存器内容。
6.几个注意事项
函数调用的时候,形参分配内存,新建一个变量,存储传递过来的实际参数的值会自动完成数据类型转换
void add(int x) { printf("x = %d\n", x);}void main() { add(12.5);}
局部变量
定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。在 main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时,main 函数中也不能使用其它函数中定义的变量。main 函数也是一个函数,与其它函数地位平等。形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。在语句块中也可定义变量,它的作用域只限于当前语句块。
全局变量
在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。
int x = 10;void add(int x) { x = x + 100;//这里是局部变量 printf("x = %d\n", x);}void main() { add(12); printf("%d", x);//这里对应的全局x}
一对大括号之间就是一个块区域,其中作用域也就是块区域中。
void main() { int x = 10; { int x = 99;//这里会屏蔽外面的x printf("%d\n", x); }; printf("%d\n", x);}
标签: #c语言中输出函数 #c语言函数的组成 #c语言函数的组成是什么 #c语言程序设计1加到100怎么算 #c函数分文件编写