函数指针
(一)、1、函数的地址 = &函数名(或者直接可以等于函数名,但较多用的还是&函数名)
2、函数名是指针常量,保存的是函数入口的地址
(二)、例子
int func(int num)
{
printf("num == %d\n",num);
}
int main()
{
func(5);
int (*p_func)(int); ☆
printf("%d\n",sizeof(p_func)); △
}
1、函数名只有一个字节:如果将☆处修改为:int *p_func(int),则还是一个字节,如果将 △ 处修改为sizeof(func)
还是一个字节
2、函数指针为四个字节:如果将☆ 处修改为int (*p_func)(int);结果为4,将△ 修改为sizeof(&func)结果为4
3、函数名是什么?是函数的入口地址
函数的入口地址是什么?&函数名
(以上两者并不矛盾,只是两种不同的表述)
函数指针数组
(一)、定义:int (*p_func_array[3])(int);
(二)、初始化:
假设前面已经定义了三个调用函数func1,func2,func3
p_func_array[0] = &func1;
p_func_array[1] = &func2;
p_func_array[2] = &func3;
(三)、调用:
假设要每个函数要调用30次:
for(i = 0;i < 30;i++)
for(j = 0;j < 30;j++)
{
p_func_array[j](5);
}
回调函数
void func4(int (*p_func)(int)){
p_func(5);
}
int main()
{
func4(&func1)
func4(&func2)
func4(&func3)
}
回调函数的好处是统一接口,增强扩展性
函数
(一)、函数可以不加形参名,比如:void swap_int(int,int);但是最好加上(二)、函数接口(就是一个函数)的三大要素
1、函数原型
2、函数的说明文档,其中包括函数的功能,函数形参的作用,函数的返回值
六、传值和传参:
例子:
#include <stdio.h>
void exchange(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int num1;
int num2;
printf("Please enter num1:");
scanf("%d",&num1);
printf("Please enter num2:");
scanf("%d",&num2);
exchange(&num1,&num2);
printf("The result is:num1 == %d,num2 == %d\n",num1,num2);
return 0;
}
假设用的是传值,则可假设栈空间内存分配如下:
函数的调用过程:
1、通过函数名找到函数的入口地址
2、给函数的形参分配空间
3、传参,将实参传给形参
4、执行函数体结构语句,交换temp,a,b
5、函数返回值返回
6、释放栈空间
7、再打印num1,num2
传值不能进行交换的原因是返回值执行过后,栈空间已经被释放,根本没有进行交换
假设用的传地址
对x,y指向的内存空间进行操作,即对a,b直接进行操作
例子:
void add_ptr(char &ptr)
{
ptr++;
}
int main()
{
char *ptr = "hello world";
add_ptr(ptr);
printf("%s",ptr);
}
ptr并不是指针本身的地址,而是h的地址,是ptr的内容,要传&ptr,对其地址进行操作,形参需要用指针的指针来接:**ptr
传参总结:
1、只读(想对操作数只使用不修改)实参变量对应空间的值传实参变量名。
2、写(想对操作数使用并且修改)实参变量对应空间的值传实参变量的地址。
另外:
1、char a[] ="hello world";可以修改因为数组分配在栈空间
2、char *a = "hello world";不可修改因为分配在全局变量区的or段
传出参数和传入参数
(一)、传出参数:output
传入参数:input
(二)、例子:
int continue_max(char *src,char *dest)
{
return max;
…………
}
int main()
{
char *src = "dqihwdcb1234365fsdnr";
char dest[100];
continue_max(dest,src);
return 0;
}
先定义一个空的字符数组dest,在经过函数填充,可带出值,dest为传出参数,src为传入参数
返回值
(一)、为什么要在主函数最后加return 0?通知系统程序正常结束,不用再做判断
char *func()
{
char ptr[100] = "hello world";
return ptr;
}
int main()
{
char *ptr = func();
printf("%s\n",ptr);
return 0;
}
不行,打印之前栈空间已经被释放
可以定义:static char ptr[] = "hello world";
或者:char *ptr = "hello world";
exit函数
1、exit(1):结束整个程序并退出(括号内可以加任意值,都可以退出)2、要看在哪一步退出?用echo$?(命令行模式下),打印当前程序结束的返回值
如果在exit(1)处结束的,则输出1,如果在exit(2)处结束的,则输出2,以此类推。
3、但是只打印一二完全没有代表性,可以这样:
if(num == 5)
{
printf("PASSWD ERROR!");
exit(1);
}
4、为了增加程序的可读性,可以用宏定义:
#define PASSWD_ERROR 2
{
exit(PASSWD_ERROR);
}