C/C++|物联网开发入门+项目实战|函数输入与输出|值传递|地址传递|连续空间的传递|嵌入式C语言高级|C语言函数的使用(1)-学习笔记(11)


参考: 麦子学院-嵌入式C语言高级-C语言函数的使用

函数概述

一堆代码的集合,用一个标签去描述它
复用化,降低冗余度
标签 ------ 函数名
函数和数组都属于内存空间,函数具备3要素:
int *p;
int a[100];
1、函数名(地址)
2、输入参数
3、返回值
在定义函数时,必须将3要素告知编译器。
int fun(int ,int ,char){};
如何用指针保存函数?
char *p;
数组 char(*p)[10];
函数 int (*p)(int,int,char)
定义函数与调用函数的区别
int fun(int a,int b)
{
xxxxx
}
int main()
{
fun(10,2);
}
示例1:函数指针与函数的类型需一致

#include <stdio.h>

int main()
{
    char (*myshow)(const char *,...); //这里必须与函数原型的类型一致,否则报错
    //c:8:12: warning: assignment from incompatible pointer type [enabled by default]
    printf("hello world!\n");

    myshow = printf;

    myshow("==============\n");

    return 0;
};
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:9:12: warning: assignment from incompatible pointer type [enabled by default]
// hello world!
// ==============
//

示例2:查看函数的地址

#include <stdio.h>

int main()
{
    int (*myshow)(const char *,...);

    printf("the printf is %p\n",printf);

    // printf("hello world!\n");

    myshow = printf;

    myshow("==============\n");

    return 0;
};
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the printf is 00000000004076D0
// ==============

示例3:直接用该地址调用:

#include <stdio.h>

int main()
{
    int (*myshow)(const char *,...);

    printf("the printf is %p\n",printf);

    // printf("hello world!\n");

    myshow =  (int (*)(const char *,...))0x00000000004076C0;

    myshow("==============\n");

    return 0;
};
// 定义指针的方式应该相同,且通过地址能够实现调用
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the printf is 00000000004076C0
// ==============

指针完成switch的功能:调用函数的第几项,效率就会非常高。
int (*p[7])(int,int); //函数地址
p[0]=fun1;
p[1]=fun2;
pday; //注册,回调,调用,知道地址和参数就能调用
在这里插入图片描述

输入参数

承上启下的功能
调用者:
只需要标签(要传递的数据) //实参
被调者:
函数的具体实现
函数的返回值 函数名定义(接收的数据){具体实现} //形参
实参传递给形参
传递的形式:
拷贝

示例:

#include <stdio.h>

void myswap(int buf) //预分配4个字节
{
    printf("the buf is %x\n",buf);
}

int main()
{
    int a = 20;

    myswap(0x123); //逐个复制给接收器

    return 0;
};
// 如果不给参数,会提示如下错误:
// 2.c: In function 'main':
// 2.c:12:5: error: too few arguments to function 'myswap'
// 2.c:3:6: note: declared here

示例2:

#include <stdio.h>

void myswap(char buf) //预分配4个字节
{
    printf("the buf is %x\n",buf);
}

int main()
{
    int a = 20;

    myswap(0x1234); //逐个复制给接收器

    return 0;
};
// 这里明显有溢出,只能存4字节
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:12:5: warning: overflow in implicit constant conversion [-Woverflow]
// the buf is 34

示例3:

#include <stdio.h>

void myswap(int buf) //预分配4个字节
{
    printf("the buf is %x\n",buf);
}

int main()
{
    int a = 20;
    char *p = "hello wordld!";

    printf("the p is %x\n",p);

    myswap(p); //

    return 0;
};
E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
2.c: In function 'main':
2.c:15:5: warning: passing argument 1 of 'myswap' makes integer from pointer without a cast [enabled by default]
2.c:3:6: note: expected 'int' but argument is of type 'char *'
the p is 40902f
the buf is 40902f

在这里插入图片描述

示例4:

#include <stdio.h>

void myswap(int ) //预分配4个字节
{
    printf("the buf is %x\n",buf);
}

int main()
{
    int a = 20;
    char *p = "hello wordld!";
    char b[10];

    printf("the p is %x\n",p);

    myswap(b); //逐个复制给接收器

    return 0;
};
// 2.c: In function 'main':
// 2.c:16:5: warning: passing argument 1 of 'myswap' makes integer from pointer without a cast [enabled by default]
// 2.c:3:6: note: expected 'int' but argument is of type 'char *'
// the p is 40902f
// the buf is 40902f

示例5:

#include <stdio.h>

void myswap(int a) //预分配4个字节
{
    printf("the buf is %x\n",a);
}

int main()
{
    int a = 20;
    char *p = "hello wordld!";
    char b[10];

    printf("the p is %x\n",b);

    myswap(b); //逐个复制给接收器

    return 0;
};
// a在函数体内外进行复制,不会冲突,访问效果不一致
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:16:5: warning: passing argument 1 of 'myswap' makes integer from pointer without a cast [enabled by default]
// 2.c:3:6: note: expected 'int' but argument is of type 'char *'
// the p is 64fe10
// the buf is 64fe10

值传递

不会对原有空间进行改变
上层调用者保护自己空间值不被修改的能力,主要用于查看

地址传递

上层,调用者让下层子函数修改自己空间值的方式
类似结构体这样的空间,函数与函数之间调用关系–》连续控件的传递

int a = 10;
fun(&a);
a===?10
示例:

#include <stdio.h>

void swap(int *a,int *b) //预分配4个字节
{
    int c;

    c = *a;
    *a = *b;
    *b = c;
}

int main()
{
    int a = 20;
    int b = 30;
    int c;

    printf("the a is %d,the b is %d\n",a,b);

    swap(&a,&b);

     printf("after swap,the a is %d,the b is %d\n",a,b);


    return 0;
};
// 地址交换
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the a is 20,the b is 30
// after swap,the a is 30,the b is 20

int a;
scanf(“%d”,a); scanf(“%d”,&a)

连续空间的传递

1、数组(数组名-标签) 用地址传递
实参:
int abc[10];

    fun(abc) //abc是地铁
形参:
    void fun(int *p) //用地址来描述数组空间
    编译器也支持以下写法:
    void fun(int p[10]) //这里的p还是指地址,管理空间大小为10

2、结构体
结构体变量
struct abc{int a;int b;int c;};
struc abc buf;
实参:
fun(buf); //变量拷贝,浪费内存,不建议用
fun(&buf)
形参:
void fun(struct abc a1);
void fun(struct abc *a2); //推荐,节约空间
两种类型:
void fun(char a);
int main()
{
char a = ‘c’;
fun(a);
a == ‘c’; //只复制,不修改
}
示例(编译错误,待查):

#include <stdio.h>

void fun(char *p)
{
    p[1] = '2';
}


int main()
{
    char buf[] = 'hello';
    fun(buf);
    return 0;
};
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:11:18: warning: character constant too long for its type [enabled by default]
// 2.c:11:5: error: invalid initializer

猜你喜欢

转载自blog.csdn.net/Medlar_CN/article/details/130270234