指针与函数

最近在看《深入理解C指针这本书》,为了不让自己忘记,就把里面的知识点记录了下来。后面的一系列文章都是这本书的笔记。

目录

指针与函数_返回指针

指针与函数_返回局部数据指针问题

指针与函数_函数指针

指针与函数_返回函数指针 

指针与函数_函数指针作参数

指针与函数_函数指针转换

指针与函数_比较函数指针


指针与函数_返回指针

在下面的函数中,我们定义一个函数,为其传递一个整数数组的长度和一个值来初始化每个元素。函数为整数数组分配内存,用传入的值进行初始化,然后返回数组地址。

int *allocateArray(int size, int value)
{
	int *arr = (int *)malloc(size * sizeof(int));
	for (int i = 0; i < size; i++)
	{
		arr[i] = value;
	}
	return arr;
}
int main()
{
	int *vector = allocateArray(5, 45);
	for (int i = 0; i < 5; i++)
	{
		printf("%d\n", vector[i]);
	}
	free(vector);//记得释放内存,以免造成内存泄漏
}

下图说明了这个函数的内存分配。左图显示return语句执行前的程序状态,右图显示函数返回后的程序状态。vector变量指向了函数内分配的内存的地址。当函数终止时,arr变量也会消失,但是指针所引用的内存还在,这部分内存最终需要释放。

函数返回指针可能存在的几个问题:

返回未初始化的指针;

返回指向无效地址的指针;

返回局部变量的指针;

返回指针但是没有释放内存。

指针与函数_返回局部数据指针问题

接上一个,这次我们不为数组分配动态内存,而是用了一个局部数组。

//局部数据指针
int *allocateArray(int size, int value)
{
	int arr[5];
	for (int i = 0; i < size; i++)
	{
		arr[i] = value;
	}
	return arr;
}

int main()
{
	int *vector = allocateArray(5, 45);
	for (int i = 0; i < 5; i++)
	{
		printf("%d\n", vector[i]);
	}
	free(vector);
}


程序运行会有问题,运行结果如下。

 

函数调用前后,内存分配图如下:

指针与函数_函数指针

声明函数指针:void (*fprt)(int );

声明函数指针类型:typedef void (*fptr) (int );

使用函数指针类型来声明函数指针变量:fptr fptr1;

int* (*f6)();//声明了一个函数指针,它指向的函数的返回值是一个指针

使用函数指针:

#include<stdio.h>

int square(int num)
{
	return num*num;
}

int main()
{
	int n = 5;
	int(*fptr1)(int);
	fptr1 = square;
	printf("%d square is %d\n", n, fptr1(n));
}

结果如下:

我们也可以向下面那样用取地址操作符对函数名进行操作,但是没有必要这么做。编译器会忽略去地址操作符。

fptr1=&square;

注:在调用函数的时候,也可以(*fptr1(n)),(*square(n));不过感觉没有必要,多此一举。知道可以这样就好。

#include<stdio.h>

typedef int(*fun) (int, int);

int add(int a, int b)
{
	return a + b;
}

int substract(int a, int b)
{
	return a - b;
}

int calculate(fun fun1, int a, int b)
{
	printf("%d\n",fun1(a, b));
}

int main(void)
{
	//函数指针做参数
	calculate(substract, 1, 2);
	fun fun2 = add;//直接这样用,不要加&,*啥的,知道就可以了。
	fun fun3 = &add;
	printf("%d\n", fun2(1, 2));
	printf("%d\n", (*fun2)(1, 2));//这里*fun2得加括号,优先级问题。
	printf("%d\n", fun3(1, 2));
	printf("%d\n", (*fun3)(1, 2));
	printf("%d\n", (*add)(1, 2));
	
	int(*funfun) (int, int);
	funfun = substract;
	printf("%d\n", funfun(1, 2));
	return 0;
}

函数指针常量:函数名

函数指针变量

函数指针类型

指针与函数_返回函数指针 

返回函数指针,其实就是返回一个函数。返回值为一个函数名就可以了。

#include<stdio.h>

int add(int num1, int num2)
{
	return num1 + num2;
}

int subtract(int num1, int num2)
{
	return num1 - num2;
}

typedef int(*fptrOperation)(int, int);

fptrOperation select(char opcode)//select函数根据输入的字符来判断返回add或者subtract
{
	switch (opcode)
	{
		case '+':return add;
		case '-':return subtract;
	}
}

int evaluate(char opcode, int num1, int num2)
{
	fptrOperation operation = select(opcode);
	return operation(num1 , num2);
}

int main(void)
{
	printf("%d\n", evaluate('+', 5, 6));
	printf("%d\n", evaluate('-', 5, 6));
	return 0;
}

运行结果如下:

指针与函数_函数指针作参数

//在一个函数中调用另一个函数
//compute函数根据函数指针参数来决定是求和还是做差
#include<stdio.h>

int add(int num1, int num2)
{
	return num1 + num2;
}

int subtract(int num1, int num2)
{
	return num1 - num2;
}

typedef int(*fptroperation)(int, int);

int compute(fptroperation operation, int num1, int num2)
{
	return operation(num1, num2);
}

int main()
{
	int num1 = 5, num2 = 6;
	printf("%d\n", compute(add, num1, num2));
	printf("%d\n", compute(subtract, num1, num2));
	return 0;
}

运行结果如下:

指针与函数_函数指针转换

一、函数指针变量指向其他格式的函数

#include<stdio.h>
int add(int num1, int num2)
{
	return num1 + num2;
}

typedef int(*fptr1)(int);
typedef int(*fptr2)(int, int);


int main()
{
	fptr2 fptr_2 = add;
	fptr1 fptr_1 = add;
	printf("%d\n", fptr_1(1, 2));//这样居然没报错,只提示一个警告。
	printf("%d\n", fptr_2(5, 6));
	return 0;
}

上面没有报错,只提示了两个警告:warning C4020: “fptr_1”: 实参太多;warning C4113: “int (__cdecl *)(int,int)”和“fptr1”的参数列表不同。

程序还是运行了出来

二、函数指针与数据指针

#include<stdio.h>
int add(int num1, int num2)
{
    return num1 + num2;
}

typedef int(*fptr)(int, int);


int main()
{
    int a = 10;
    int *p = &a;
    fptr fptr1 = add;
    fptr1 = p;
    printf("%d\n", *fptr1);
    printf("%d\n", *(int *)fptr1);
    p = add;
    //printf("%d\n", p(5, 6));//这里不强制类型转换的话会报错
    printf("%d\n", ((fptr)p)(5, 6));
    return 0;
}

程序运行结果:

无法保证函数指针和数据指针相互转化后正常工作。

总结:自己用函数指针的时候还是规规矩矩的来把。

指针与函数_比较函数指针

我们可以用相等和不等操作符来比较函数指针,来判断函数指针是否指向了某一个函数。

//比较函数指针,来判断函数指针是否指向了那个函数
#include<stdio.h>
int add(int num1, int num2)
{
	return num1 + num2;
}
typedef int(*fptr)(int, int);

int main()
{
	fptr fptr1 = add;
	if (fptr1 == add)
	{
		printf("fptr1 points to add.\n");
	}
	else
	{
		printf("fptr1 doesn't point to add.\n");
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值