文章目录
- 函数概述
- 输入参数
- 示例:
- 值传递
- 地址传递
- 连续空间的传递
参考: 麦子学院-嵌入式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