嵌入式C语言学习笔记-函数

函数

函数概述
【函数概述】复用化,一堆代码的集合,用一个标签(函数名)去描述它,访问他
函数三要素,函数名 (地址)输入参数,返回值
使用指针保存函数地址?
定义函数和调用函数的区别?
​
标签就是地址,但由于访问方式的不同,得到的结果也不同fun(1)###fun(21)
    
输入参数
【承上启下】的功能
1.调用者
函数名(要传递的数据)      实参
​
2.被调者 -函数的具体实现
函数的返回值  函数名(接收的数据)  形参
{
    xxxx
    具体实现
}
​
实参传递给形参
传递的形式:【拷贝】
值传递
交换函数swap()
传递的是备份,原有的空间不会有任何改变
上层调用者,保护自己的空间【不被修改】的能力

地址传递
门牌号
上层调用者,让下层子函数【修改】自己空间值的方式
​
空间的读写
只读空间:const char *p;
​
char *p;该空间可以修改
​
举例:
sprintf();格式化字符串处理
int sprintf(char *str,const char *format,...);
​
int a=12;
char buf[10];
sprintf(buf,"%d",a);

连续空间的传递
连续空间的只读性
结构体变量-建议地址传递
struct abc{int a;int b;};
struct abc buf;
实参:fun(buf);  fun(&buf);
形参:void fun(struct abc a);   void fun(struct struct abc *a);
​
​
连续空间的传递【数组】-考虑地址传递
数组名,数组标签,标签就是地址
实参:int abc[10]; 
      fun(abc);
形参:void fun(int *p);
  
字符空间和非字符空间最大的区别:结束标志的不同
字符空间:
空间首地址,结束标志
​
结束标志:内存中存放了0x00(1B),字符空间
        非字符空间0x00,不能当成结束标志
    
void fun(char *p)//const char *p
{
    int i=0;
    while(p[i]){
        //p[i]操作...
        i++;
    }
}
​
举例:编写一个strlen()函数,具体的实现可根据CPU决定
分析:1.对连续空间读内存,传递首地址
     2.只读字符串 const char *p;
int strlen(const cahr *p)
{
    int i=0;
    /*错误处理,判断输入参数是否合法*/
    if(p==NULL){
    //return...
    }
    /*内存处理,遍历*/
    while(p[i]){//结束条件
    **********
    i++;
    }
}
​
编写一个strcpy()函数
void strcpy(char *dest,const char *src);
​
""--->初始化const char *
char buf[10] --->初始化char *
非字符空间
int *p;
unsigned char *p;
....
0不能作为结束标志,结束标志:数量
​
void fun(unsigned char *p,int len)
{
    int i;
    for(i=0;i<len;i++)
    {
        ....
    }
}
​
void *:在形参中,数据空间的标识符,可以接收任何类型传入,子函数反向修改上层空间的内容
大小:len
​
举例:void *memcpy(void *dest,const void *src,size_t n);
​
int fun(void *buf,int len)
{
    unsigned char *tem=(unsigned char *)buf;
    for(int i=0;i<len;i++)
    {
        tem[i]...
    }
    
}

返回值
基本语法
调用者
    a=fun();
被调者  实现
    int fun()
    {
        return num;
    }
    
【拷贝】
返回基本数据类型
函数承上启下的作用,修改上层函数的值
int fun1(void);     main:int a=0;a=fun1();
void fun2(int *p);  main:int a=0;fun2(&a);//传递的是a的地址,a的值可以被下层函数修改
​
【应用】当一个函数需要两个int返回值时:
int fun(int *p);
​
指向一个新的地方:
int *fun1(void);
int main()
{
    int *p;
    p=fun1();
}
​
定义成*p是想修改p指向的值,定义成**p是想修改p指向的地址
void fun2(int **P);
int main()
{
    int *p;
    fun2(&p);
}
​
返回连续空间类型
指针作为空间返回的唯一的数据类型
地址操作:指向的合法性【不是局部空间】
​
不合法的举例:在fun函数中开辟的空间 buf ,随着被调用函数的结束,空间即被回收释放,主函数中的指针相当于指向了一片已经消失了的空间
char *fun(void)
{
    char buf[]="hello world!";
    return buf;
}
int mian()
{
    char *p;
    
    p=fun();
    printf("the p is %s\n",p);
    return 0;
}
​
​
---》
1.只读区
char *fun(void)
{
    return "hello world!";//字符串常量就是一个地址值,存放在常量区中
}
2.静态区
添加static关键字
3.堆区
char *s=(char *)malloc(100);//申请
strcpy(s,"hello world");//初始化
main:free(p);//释放
使用者:
int *fun();
int *p=fun();
函数内部实现
基本数据类型 fun(void)
{
    基本数据类型 ret;
    ......
    ret=xxx;
    return ret;
}
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值