【无标题】

本文详细介绍了C语言中的函数概念,包括函数的定义、分类(如主函数、库函数、自定义函数)、参数和返回值类型,以及无参无返、有参无返和有参有返函数的使用。还探讨了全局变量和局部变量的作用域,数组作为参数的传递方式,以及指针函数和函数指针的概念。此外,提到了值传递和地址传递的区别,并提供了递归和存储类型的解释,如const和static的用法。最后,介绍了宏定义及其在多文件编译中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、函数

函数:实现特定功能的代码块,C语言称为函数语言。

作用:解决重复代码所带来的劳动量,使程序开起来更加简洁,运行速度快。

1> 主函数main: 一个程序里面只能有一个主函数,主函数可以调用任何函数,但是主函数不可以被任何一个函数调用

2> IO函数:scanf printf getchar putchar gets puts

3> str函数:strlen strcat strcpy strcmp

1.1 函数定义

定义格式:

数据类型 函数名(参数列表) //函数头

{

     函数体 ;                  //{}里面的所有称为函数体

}

int main(int argc, const char *argv[])

{

return 0;

}

注意: 数据类型:基本类型、构造类型、指针类型、空类型

函数名: 需要满足名规范【但是在定义函数时,函数名不可以重复】

():函数的标志,不可以省略 参数列表:可以是多个,或者0个

{}:不可以省略

1.2 函数的分类

1> 库函数:系统自带的函数

2> 自定义函数:由程序员自己封装的函数

3> 有无参数函数:取决于参数列表

1.如果参数列表存在:则称为有参函数

2.如果参数列表不存在:则称为无参函数

4> 有无返回值函数:取决于函数的数据类型,

1.如果数据类型是void: 称为无返函数

2.如果数字局类型不是void:称为有返函数

 void sum() //无参无返函数

int sum() //无参有返函数

void sum(int a,int b)//有参无返函数

int sum(int a,int b)//有参有返函数

1.3 无参无返函数+调用

定义格式

void 函数名(void)//void可写可不写  void sum()

{ {

int a=1,b=2;printf("a+b=%d",a+b);

} }

调用格式:

函数名();                      sum();

1.3.1自定义函数写在主函数的上面

 1.3.2自定义函数写在主函数的下面

 

 1.3.3自定义函数声明写在预处理阶段

 注意:自定义函数写在主函数下面运行速度,相对较快,对成员相对友好。

1.4 全局变量、局部变量

1.4.1 全局变量

全局变量:在函数外定义的变量。

作用域:从定义开始,到整个工程结束

1.4.2 局部变量

局部变量:在函数内定义,参数列表

作用域:在本函数内有效

空间: 当函数调用局部变量分配空间,函数调用结束,空间释放

 1.4.3 全局变量和局部变量重名

 

 1.5 有参函数

定义格式

void 函数名(参数列表)                     void sum(int m,int n) //多个参数之间使用逗号隔开

{ {

int a=1,b=2;printf("m+n=%d",m+n);

} }

调用格式:

          函数名(参数变量名);                      sum(a,b);

1> 传参:被调函数需要使用主调函数的局部变量,传递参数

2> 实参和形参的类型

实际参数:变量 常量 表达式 函数

形式参数:变量 函数指针

3> 传参的注意事项

1.个数必须一致

2.类型可以不一致【以形参为主,发生自动或强制转换】

3.一 一对应

4.形式参数必须加数据类型

5. 形参和实参的变量名可以不一致

1.5.1 数组做参数

注意:数组做参数,只传递数组组名

1> 一维数组做参数,数组或指针接收

void fun(int arr[],int len);

void fun1(int *p,int len);

int main(int argc, const char *argv[])

{

int arr[]={11,22,33,44,55};//局部变量:只能在主函数

printf("sizeof(arr)=%ld\n",sizeof(arr));

int len=sizeof(arr)/sizeof(arr[0]);

fun(arr,len);//数组做参数传递数组名

fun1(arr,len);

return 0;

}

//在自定义函数fun输出

//形参的数组长度必须要大于等于实参的数据长度

//一般省略不写,默认是实际参数的数据长度

void fun(int arr[],int len)    //arr看似是数组,实际是指针

{

for(int i=0;i<len;i++)

   {

printf("%d\t",arr[i]);

} }

void fun1(int *p,int len)

{

for(int i=0;i<len;i++)

{

printf("%d\t",*(p+i));

} }

2> 字符串做参数,数组或指针接收

#include <stdio.h> #include <string.h>

#include <stdlib.h> void fun(char *p);

int main(int argc, const char *argv[])

{

char str[]="hello";       //局部变量,只能主函数使用

fun(str);

printf("str=%s\n",str);

return 0;

}

//在自定义函数中实现大转小,小转大写

void fun(char *p)

{

int len=strlen(p);

while(*p!='\0')

{

if(*p>='A' && *p<='Z')

{ *p+=32; }

else if(*p>='a' && *p<='z')

{

*p-=32;

}

p++; } }

3> 二维数组做参数,数组和指针接收

void output(int (*p)[3],int line,int row);

int main(int argc, const char *argv[])

{

int arr[][3]={11,22,33,44,55,66};//局部变量

int line=sizeof(arr)/sizeof(arr[0]);

int row=sizeof(arr[0])/sizeof(arr[0][0]);

output(arr,line,row);

return 0;

}

//自定函数实现输出

void output(int (*p)[3],int line,int row)

{

for(int i=0;i<line;i++)

{

for(int j=0;j<row;j++)

{

// printf("%d\t",arr[i][j]);

printf("%d\t",*(*(p+i)+j));

}

printf("\n"); } }

1.5.2 数组做参数练习

练习1:实现简单选择排序【一维数组做参数】

要求:使用指针接收

定义一个函数input实现输入

定义一个函数select_sort实现排序

定义一个函数output实现输出

 

 练习2:实现字符串拷贝函数

 

1.6 有返回值函数

有返回值函数:主调函数需要使用被调函数的局部变量

 

注意:

1> 如果数据类型是void默认是无返回值函数

2> 如果返回的类型是int类型,可以默认不写

3> return: 返回 结束函数

格式1:return 表达式

格式2:return(表达式)

1.表达式:变量、常量、表达式

2.return位置可以任意,一般放在最后

3.return一次只可以返回一个变量

4.return可以写多个,但是只有第一个有效

5.当函数的返回类型和函数的数据类型不一致时,选用函数的数据类型

练习:计算字符串的长度

 

 练习2:使用数组指针接收二维数组

1.定义有参有返函数,返回最大差值

2.定义有参有返函数, 返回最大和

 

1.7 指针函数

本质上一个是函数,主要返回的是一个指针

 定义格式:

数据类型 *函数名(参数列表)

{

函数体;

return 地址;//注意地址不可以是局部变量的地址

}

题目:返回两个变量,需要借助于数组

 

 

 练习:实现字符串拷贝函数

返回拷贝后字符串的首地址

 

1.8 函数指针

函数指针本质上是一个指针,用来指向函数的地址

定义格式:

数据类型 (*函数指针名)(参数列表);

void sum() //无参无返函数 void (*p)(void)

int sum() //无参有返函数 int (*p)(void)

void sum(int a,int b)//有参无返函数 void (*p)(int a,int b) -->void (*p)(int,int)

int sum(int a,int b,float c)//有参有返函数 int (*p)(int ,int,float)

注意:

1> 函数名表示函数的首地址

2> 没有办法计算函数所占空间的大小

3> 指针指向函数时,通过p调用,表示通过函数首地址直接调用函数,*p调用,表示通过函数首地址取值,根据值调用函数,注意:***p这里面的*个数可以是任意的。

 

 1.8.1 函数指针练习

 

 

 

1.9 函数指针数组

函数指针数组本质上是一个数组,存储多个函数地址的

定义格式: 数据类型 (*函数指针数组名[常量表达式])(参数列表)

 

1.10 值传递和地址传递

1.10.1 值传递

1> 值传递的是值

2>实参和形参分别占有不同的存储空间

3>形参的改变不影响实参

4>单向传递:实参传递给形参

 

1.10.2 地址传递

1> 地址传递传递的地址:数组名,指针

2>地址传递传递的地址

3>形参和实参共享存储空间

4>形参的改变影响实参

5>单项传递:实参传递给形参

 

 1.10.3两个数的交换练习

 

1.11 递归

递归:函数自己调用自己

1> 直接递归:函数自己调用自己 【死循环】

2> 间接递归:多个函数之间相互调用

3> 递归组成:

递归出口:结束递归的

递归前进段/递归公式: 递归调用

4> 循环可以用来解决问题规模较小的情况,递归常用来解决问题规模较大的时候,递归的运行速度慢

 1.11.1 递归练习

 

 

 

 

 

 

1.12 存储类型

1,const[重点]

1> const修饰的变量不可以改变值

2> const修改的全局变量在.ro段

3> const修改的局部变量在栈区

4> const和指针

const int *p: *在const的右边,const修饰的是值,值不可以改变,地址可以改变

int const *p:*在const的右边,const修饰的是值,值不可以改变,地址可以改变

int * const p:*在const的左边,const修改的是地址,值可以改变,地址不可以改变

const int * const p:const修改的是地址和值,值不可以改变,地址不可以改变

2.static【重点】

2.1>static局部变量

static修饰的局部变量:延长生命周期,作用类似全局变量

 注意:static修饰的局部变量,作用域依旧是fun函数中能使用 ,但是生命周期,也就是地址没有释放,延长至文件结束

2.2>static修饰全局变量

1.static修饰未初始化的全局变量,默认值为0

2.static修饰的全局变量,不可以跨文件使用

注意:在同一目录下创建或打开文件 vsp 文件名,

多个文件编译:

gcc 文件名1文件名2......

2.3>static修饰函数

static修饰的函数,不可以跨文件使用

3.extern

作用:引入外部变量,但是不可以引入静态变量的值

4.register【了解】

作用:寄存器变量,变量的空间在寄存器

1> 寄存器变量运行速度最快【寄存器> cache高速缓存 > 内存】

2> 寄存器变量不可以取地址操作

5.volatile【了解】

作用:防止内存优化,保持内存的可见性

6.auto

自动类型,一般默认不写就是自动类型的变量

自动类型修饰的局部变量在栈区,全局变量在静态区

1.13 宏

宏:只做替换,不做计算,不做正确性的检查,常量[不变]

1.13.1 宏定义

定义格式: #define 宏名 字符串

 

 1.13.2 宏函数

 

 

1.13.3 多文件编译

头文件:预处理命令,全局变量,函数声明

自定义文件:自定义函数

主函数文件:主函数

作业:使用多文件编译【复习】

实现字符串技能

三个文件:main.c head.h test.c

1> 通过指针指向字符串,实现字符串逆置 void MyStrRev(char *p) //p要逆序的字符串

3> 字符串连接 char *MyStrcat(char *dest,const char *src)//dest:连接到dest字符串中,src字符串不变

4> 字符串比较函数int MyStrcmp(const char *s1,const char *s2) s1存储第一个字符串 s2存储第二个字符串

5> 字符串拷贝char *MyStrcpy(char *dest,const char *sec) dest:拷贝后的字符串 src源字符串

6> 字符串长度long Mystrlen(const char *s1) s1存储字符串

7> 使用递归实现斐波那契 FibonaciRec(n-1)+FibonaciRec(n-2)

8> 实现单词的逆置例如:char str[]="hello my student",输出结果是“student my hello”

思路:先整体对字符串逆置,在对每一个单词逆置

9> 指针指向一维数组,实现冒泡排序

10> 指针指向一维数组,实现简单选择排序

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值