嵌入式学习Day3-4(C函数、参数传递、指针函数、函数指针)(2024.03.13-14)

本文详细介绍了C语言中的函数概念,包括函数定义、全局变量与局部变量的区别、值传递与地址传递的原理、数组参数处理以及指针、回调函数和递归函数的使用。

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

嵌入式学习Day3-4(2024.03.13-14)

C语言函数

函数定义

全局变量和局部变量

全局变量局部变量静态局部变量
作用域定义于函数外,同一文件中的任何位置都可使用定义于函数内,函数体内使用函数体内使用
生命周期定义时分配空间,main函数结束时系统回收空间定义时分配空间,函数调用结束时系统回收空间在函数内定义,函数调用后随main结束而被回收
初始值0随机0
#include<stdio.h>

int a=10; //全局变量
/*对全局变量操作*/
void f_a(){
	a++;
	printf("a = %d \n",a);
}
/*对局部变量操作*/
void f_b(){
	int b=10;
	b++;
	printf("b = %d \n",b);


}


int main(void){
	f_a(); //全局变量生命周期随main函数,会一直加
	f_a();
	f_a();
	printf("=============================================\n");
	f_b();//局部变量生命周期随函数调用,每次都为11
	f_b();
	f_b();
}

在这里插入图片描述

#include<stdio.h>

/*对静态局部变量操作*/
void f_b(){
	static int b=10;
	b++;
	printf("b = %d \n",b);


}


int main(void){
	f_b();//静态局部变量生命周期随函数调用,main函数结束后才回收
	f_b();
	f_b();
}

在这里插入图片描述

函数参数传递

值传递
#include<stdio.h>
//值传递,形参为具体类型
void f_b(int value){
	value++;   //值传递,不会改变实参的值,相当于函数内定义了一个局部变量value,将实参值赋给局部变量value
	printf("value = %d \n",value);
	return ;
}


int main(void){
	int value1=10;
	f_b(value1);//value1 为实参,值传递时并不会被改变,形参value接受实参vlaue1的值
	printf("vlaue1 = %d \n",value1);
	return 0;
}

在这里插入图片描述

地址传递
#include<stdio.h>
//地址传递,形参为地址类型
void f_b(int *value){
	*value+=1;   //地址传递,传递变量地址,通过对指针的操作,直接改变地址指向的内存的值
	return ;
}


int main(void){
	int value1=10;
	f_b(&value1);//参数为value1的地址,通过指针改变value1的值
	printf("vlaue1 = %d \n",value1);
	return 0;
}

在这里插入图片描述

数组参数
/*数组作为参数时实际上传的是参数首地址*/

void fun(int []){
	//statement
}
void fun1(int *p){
	//statement
}
int main(){
	int a[10]={0};
	fun(a);
	fun1(a); //数组名为首地址,数组名可看作一个指针变量
}
函数参数总结

不管是值传递还是参数传递,其本质都是形参与实参之间值的复制。不同之处在于值传递,参数传递后形参和实参就没有联系了,对形参的操作不会影响实参。但是,地址传递传递的是实参地址,实参和形参指向同一个地址,通过对指针的操作,形参和实参都可以通过地址修改同一个内存地址中的值

指针函数

指针函数是一个函数,返回值为一个地址
定义: type * fun(type a,type b…)
返回值是地址时要注意,若返回的地址是函数内的局部变量应该使用static 修饰变量,否则会存在野指针问题==》函数调用完后,局部变量被系统回收,但是却返回了局部变量的地址,此时该地址不合法。

#include<stdio.h>


int * fun_a(){
	int a[10]={0};
	return a; //野指针
}

int main(){
	int * p=fun_a();
}

在这里插入图片描述

#include<stdio.h>
  

int * fun_a(){
        static  int a[10]={0};
        return a; //使用static修改局部变量的生命周期后编译不报错
}

int main(){
        int * p=fun_a();
        printf("%d \n",sizeof(p));
}

函数指针

函数指针本质上是一个指针,保存函数的地址。通过函数指针可以调用我们需要的函数
定义: 函数返回值数据类型 (*指针变量名)(类型1 参数1,类型2 参数2…);
(1)函数名代表函数的首地址(联系数组,数组指针)
(2)定义函数指针时可以省略参数

#include<stdio.h>
  
/*函数指针*/
void fun_a(int v1,char * v2){
        printf("调用函数fun_a()\n");
        printf("输入的参数是 v1= %d ,v2= %s \n",v1,v2);
        return ;
}

int main(){
        char buf[20]="hello world";
        void (*p)(int,char *)=fun_a; //将函数地址赋值给函数指针
        fun_a(1998,buf); //通过函数名调用函数
        printf("=========================================================\n");
        p(2024,buf);     //通过函数指针调用函数
        printf("打印函数名和函数指针指向的地址   &fun_a=%p  &p=%p\n",fun_a,p);
}

root@wangjudealy:/learn# gcc 0314.c 
root@wangjudealy:/learn# ./a.out 
调用函数fun_a()
输入的参数是 v1= 1998 ,v2= hello world 
=========================================================
调用函数fun_a()
输入的参数是 v1= 2024 ,v2= hello world 
打印函数名和函数指针指向的地址   &fun_a=0x56109500a189  &p=0x56109500a189


回调函数

将函数指针作为参数传递给另一个函数,并在另一个函数体内通过函数指针调用函数。

#include<stdio.h>
  
/*数组指针*/
void fun_a(int v1,char * v2){
        printf("调用函数fun_a()\n");
        printf("输入的参数是 v1= %d ,v2= %s \n",v1,v2);
        return ;
}
void fun_b(void (*q)(int,char *)){
        printf("调用函数fun_b()\n");
        q(2024,"hello");//通过函数指针参数调用函数

}

int main(){
        fun_b(fun_a);

}

root@wangjudealy:/learn# gcc 0314.c 
root@wangjudealy:/learn# ./a.out 
调用函数fun_b()
调用函数fun_a()
输入的参数是 v1= 2024 ,v2= hello 

递归函数

在函数体中调用函数自己
一般递归函数要设置一个条件,作为结束递归的条件

#include<stdio.h>
/*求阶乘函数*/
int t=0;
int fun_a(int num){
        if(num>1){
          printf("递归 %d 次,num=%d\n",++t,num);
          return num*fun_a(num-1); //此处使用num*fun_a(--num)会少循环一次
        }
        else {
          printf("最后一次递归\n");
          return 1;   //递归出口 ==》满足条件时不在递归
        }

}

int main(){
        int p = fun_a(4);
        printf("%d \n",p);
        return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值