【C语言】

文章详细阐述了指针函数的概念,强调了不能返回局部变量地址的原因,并提供了可以返回的地址类型。接着,介绍了函数指针的用法,包括如何定义、赋值和调用。此外,文章还讨论了回调函数的场景以及typedef在定义新类型名中的作用。最后,提到了函数指针数组和指向函数指针数组的指针的应用。
摘要由CSDN通过智能技术生成

指针函数

本质是一个函数,返回值是一个指针类型
注意:指针函数不能返回局部变量的地址
因为函数调用结束后,局部变量占用的内存空间就被操作系统回收了

可以返回:
1.全局变量的地址
2.static关键字修饰的局部变量的地址
3.由参数传递过来的地址

#include <stdio.h>

int temp2 = 0;

int *my_add(int x, int y){
	//int temp = x+y;
	//return &temp;//错误的 不能返回局部变量的地址
#if 0
	//正确的 可以返回全局变量的地址
	temp2 = x+y;
	return &temp2;
#endif

	//static关键字可以将局部变量的生命周期延长至整个程序结束
	static int temp3 = 0;
	temp3 = x+y;//正确的 

	return &temp3;
}

char *my_strcpy(char *dest, const char *src){
	char *temp = dest;
	while(*src){
		*temp++ = *src++;
	}
	*temp = *src;
	return dest;//也可以返回由参数传递过来的地址
}


int main(int argc, const char *argv[])
{
	int *p = my_add(10, 20);
	printf("%d\n", *p);

	char s1[32] = "12345678";
	char s2[32] = "hello";
	char *q = my_strcpy(s1, s2);
	printf("%s\n", q);//hello
	printf("q = %p   s1 = %p\n", q, s1);//相等的

	return 0;
}

函数指针

本质是一个指针,指向一个函数。

格式:

返回值类型  (*函数指针名)(函数的形参表);
例:
#include <stdio.h>

int my_add(int x, int y){
	return x+y;
}

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;
	int ret1 = my_add(a, b);
	printf("ret1 = %d\n", ret1); //30

	//定义一个函数指针 指向 my_add 函数
	int (*p)(int, int) = NULL;
	p = my_add;  //函数名 就是函数的首地址
	//函数指针指向函数之后 就可以通过函数指针调用函数了
	int ret2 = p(a, b);
	printf("ret2 = %d\n", p(a, b)); //30

	return 0;
}

函数指针的典型使用场景----回调函数

#include <stdio.h>

int my_add(int x, int y){
	return x+y;
}

int my_sub(int x, int y){
	return x-y;
}

//所谓的回调函数是指用函数指针做位函数的形参
//在函数中通过函数指针来调用函数 具体调用的是哪一个
//取决 jisuan这个函数的调用者给它传的第三个参数是什么
//传什么 通过函数指针调用的就是什么 ----所以叫做回调函数
int jisuan(int x, int y, int (*p)(int, int)){
	return p(x, y);
}

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;
	printf("%d\n", jisuan(a, b, my_add)); //30
	printf("%d\n", jisuan(a, b, my_sub)); //-10

	return 0;
}

linux系统中,signal函数中就是使用了回调函数来实现的。

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
//此处的 handler 是一个能指向 返回值为 void 形参列表为 (int)
//的函数的 函数指针

signal函数使用实例:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void my_function(int signum){
	printf("hqyj\n");
}

int main(int argc, const char *argv[])
{
	signal(SIGINT, my_function);

	while(1){
		printf("hello world\n");
		sleep(1);
	}

	return 0;
}

函数指针数组

本质是一个数组,数组中的每个元素都是一个函数指针。
格式:

返回值类型  (*函数指针数组名[下标])(函数的形参表);
例:
#include <stdio.h>

int my_add(int x, int y){
	return x+y;
}

int my_sub(int x, int y){
	return x-y;
}

int main(int argc, const char *argv[])
{
	//定义了一个函数指针数组,数组中有2个元素
	//每个元素都是一个能指向 返回值为 int 形参列表为(int, int) 的函数的函数指针
	int (*p[2])(int, int) = {NULL};
	//取出数组的一个元素后 操作就和操作 一个函数指针是一样的了
	p[0] = my_add;
	p[1] = my_sub;

	//可以通过函数指针数组来调用函数
	int a = 10;
	int b = 20;
	printf("a+b = %d\n", p[0](a, b)); //30
	printf("a-b = %d\n", p[1](a, b)); //-10

	return 0;
}

指向函数指针数组的指针

本质是一个指针,指向一个函数指针数组。
格式:

返回值类型 (*(*指针名))(函数的形参表);
例如:
#include <stdio.h>

int my_add(int x, int y){
	return x+y;
}

int my_sub(int x, int y){
	return x-y;
}

int main(int argc, const char *argv[])
{
	int (*arr[2])(int, int) = {my_add, my_sub};

	//定义一个指针 指向函数指针数组
	int (*(*p))(int, int) = NULL;
	p = arr;

	//可以指向函数指针数组的指针来调用函数
	int a = 10;
	int b = 20;
	printf("a+b = %d\n", p[0](a, b)); //30
	printf("a-b = %d\n", (*(p+1))(a, b)); //-10

	return 0;
}

typedef

typedef 是用来给类型起别名的。

例:
#include <stdio.h>

typedef unsigned long long int ulli;
//本来是定义变量的语句 如果前面加上了 typedef
//原来的变量名 就变成了新的类型名

int main(int argc, const char *argv[])
{
	unsigned long long int m;
	m = 100;
	ulli n = 100;
	printf("m = %lld\n", m);//100
	printf("n = %lld\n", n);//100

	return 0;
}

C语言中常见的定义变量的语句:

int a;
int *a;
int **a;
int a[5];
int a[3][4];
int *a[5];
int (*a)[5];
int (*a)(int);
int (*a[5])(int);
int (*(*a))(int);

把变量名去掉,剩下的就都是类型名了

int ;
int *;
int **;
int [5];
int [3][4];
int *[5];
int (*)[5];
int (*)(int);
int (*[5])(int);
int (*(*))(int);

本来是定义变量的语句 如果前面加上了 typedef
原来的变量名 就变成了新的类型名

typedef int a;
typedef int *a;
typedef int **a;
typedef int a[5];
typedef int a[3][4];
typedef int *a[5];
typedef int (*a)[5];
typedef int (*a)(int);
typedef int (*a[5])(int);
typedef int (*(*a))(int);

typedef 和 define 有什么区别?
1.宏定义是在预处理阶段完成替换的,而typedef是类型的重定义,在编译阶段检查;
2.typedef要求结尾必须加分号 而宏定义不强制要求;
3.typedef是给类型起别名,而宏定义只是一个简单的替换;

#include <stdio.h>

#define hqyj1 int *
typedef int * hqyj2;

int main(int argc, const char *argv[])
{
	int a = 10;
	int b = 20;

	//此时 p1 和 p2 都是指针
	hqyj2 p1, p2;
	p1 = &a;
	p2 = &b;

	//此时 q1 是指针  而 q2 就是一个普通的 int 变量
	hqyj1 q1, q2;
	q1 = &a;
	q2 = &b;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值