深入理解C语言指针——挑战C指针笔试题(4)

63 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

一级指针传参

#include <stdio.h>
void print(int *p, int sz)  //一级指针传参,一级指针接收
{
    int i = 0;
    for(i=0; i<sz; i++)
    {
        printf("%d\n", *(p+i));
    }
}
//void print(int p[],int sz) 
//数组接收,也即一级指针接收,不提倡这样写
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9};
    int *p = arr;
    int sz = sizeof(arr)/sizeof(arr[0]);
    //一级指针p,传给函数
    print(p, sz);
    return 0;
}

思考: 当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

//以int型指针为例
void test(int* p)
{
}
int main()
{
	int x=0;
	int* px=&x;
	int arr[10];
	test(&x);//整型地址
	test(px);//一级指针
	test(arr);//一维数组名,即首元素地址,int*
	return 0;
}

二级指针传参

void test(char** p )
{
}
int main()
{
	char ch = 'c';
	char* pc = &ch;
	char* *ppc = &pc;
	char* arr[3];
	test(&pc); //一级指针的地址,即二级指针
	test(ppc); //二级指针
	test(arr); //数组名,首元素地址,首元素为一级指针,所以为二级指针
 	return 0;
}

思考: 当函数的参数为二级指针的时候,可以接收什么参数?

其实和上面一样,你们可以思考一下!

函数指针

首先看一段代码:

#include <stdio.h>
void test()
{
    printf("hehe\n");
}
int main()
{
    printf("%p\n",  test); //函数名 就是函数地址
    printf("%p\n", &test); //&函数名 也是函数地址
    
    return 0;
}

运行结果 在这里插入图片描述那么如何将test()函数指针保存起来呢?

void test()
{
 printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();  //函数指针类型
void *pfun2();    //函数,函数的返回值是void*

函数指针类型 指针都是有类型的 整型指针 int* 数组指针 int (*)[] 函数指针 返回值 (*)(参数....)

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*pf)(int, int) = Add;
	int sum = (*pf)(3, 5);   //对函数指针解引用
	printf("sum = %d", sum);
	sum = pf(3, 5);          //因为 Add和&Add相同,即Add等价于 pf
	printf("sum = %d", sum);
	return 0;
}

在这里插入图片描述有趣的代码

//代码1
(*(void (*)())0)(); 
//void (*)()为函数指针
//(void (*)())0 将0强制类型抓换成函数指针的地址
//(*(void (*)())0)() *地址,调用0地址处的这个函数
//函数的返回值空,参数为空
//代码2
void (*signal(int , void(*)(int)))(int);
//void(*)(int) 函数指针,返回值void,参数int 
//void (*signal(int , void(*)(int)))(int)
// signal是函数名 
//返回值是void(*)(int)
// 参数int 和函数指针 void(*)(int)
//这是一个函数的声明

当我们看到代码2很难看懂这个代码! 可以简化吗?

void (*signal(int , void(*)(int)))(int);
//既然这个函数的返回值类型是 void(*)(int) 
//那我们可以写成
// void(*)(int) signal(int , void(*)(int));
//但是这样会语法错误 error

在这里插入图片描述函数指针类型重命名 在这里插入图片描述简化

typedef void(*ptr_t) (int);   //正确的类型重命名
 ptr_t signal(int, ptr_t);  //简化

在这里插入图片描述 上面的代码出自《C陷阱和缺陷》 有兴趣的伙伴可以尝试阅读!