指针进阶的学习

目录

前言

一、指针的类型

二、不同类型指针的介绍

2.1字符指针

2.2数组指针

2.2.1如何创建数组指针

2.2.2数组指针的使用

2.3指针数组

2.3.1如何创建指针数组

2.3.2如何使用指针数组

2.4函数指针

2.4.1函数指针的使用

例题

2.5函数指针数组

2.5.1函数指针数组的使用

2.6指向函数指针数组的指针 

2.6.1使用

2.7回调函数

总结



前言

关于指针我们知道,

1.指针是一个变量,用来存放地址,地址唯一识别一块内存空间。

2.指针的大小是4个字节或8个字节。

3.指针有类型,指针的类型决定啦它解引用时的权限


一、指针的类型

1.字符指针

2.数组指针

3.指针数组

4.函数指针

5.函数指针数组

6.指向函数指针数组的指针

7.回调函数

二、不同类型指针的介绍

2.1字符指针

字符指针类型我们用char *来表示,这里我们必需知道字符指针放的其实是地址

例:

#include <stdio.h>
int main()
{
    char str1[] = "hello.";
    char str2[] = "hello.";
    const char *str3 = "hello.";
    const char *str4 = "hello.";
    if(str1 ==str2)
 printf("str1 and str2 are same\n");
    else
 printf("str1 and str2 are not same\n");
       
    if(str3 ==str4)
 printf("str3 and str4 are same\n");
    else
 printf("str3 and str4 are not same\n");
       
    return 0;
}

str1和str2是两个不一样的字符串,所以地址也不会相同,在两者开始比较时,是比较的地址,所以不相同。

指针str3和str4是指针,存放的是地址,在此题中存放的都是hello.的首地址,首地址都是相同的,所以输出结果是same

2.2数组指针

顾名思义,数组指针就是指向数组的指针。本质上还是指针,指向的内容是数组。

数组指针是如何定义和使用的?

2.2.1如何创建数组指针

                             

 parr和*先结合说明parr指针变量,让后指向的是数组大小为10的整形数组;

*注:*parr[10],他们结合性不一样,parr和【10】的结合性比*和parr高,为啦准确表示数组指针我们必须要加括号。

我们来看一下arr的地址有&arr有何不同用法上有何不同。

我们注意到arr,&arr,parr地址都是相同的即数组首元素地址。

但是地址往下走的时候却不一样。

arr+1走一个整形大小;

&arr+1走的是整个数组的大小,直接到数组结尾;

parr+1走的也是是整个数组的大小,直接到数组结尾;

 由此我们得出arr的地址是首元素地址

&arr和parr是整个数组的地址

2.2.2数组指针的使用

void print_arr(int(*arr)[5], int row, int col) 
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
	print_arr(arr, 3, 5);
	return 0;
}

在二维数组中arr的地址不是首元素地址,而是第一行元素的地址

所以我们在设置参数时应当设置成数组指针,即int(*arr)[5];

我们在输出时,按照二维指针的写法就行。

2.3指针数组

指针数组的定义:存放指针的数组

2.3.1如何创建指针数组

int  *arr[3]

整形指针数组,这里强调arr与【3】的结合性更强

2.3.2如何使用指针数组

 这里arr里面存放的是三个字符串的地址,并不是字符串本身,解引用时,我们可以用*,当然也可以使用数组的方式。

我们应当把指针数组*arr[3]与数组指针(*arr)[3]区分开,我们可以用结合性的方法来区分,看它先跟谁结合,

第一个它先跟【】结合所以它本质时数组,即指针数组, 第二个它先跟*结合所以本质是指针,即数组指针。

2.4函数指针

函数指针:指向函数的指针。    int (*p)()

p先于*结合代表它是指针,然后与()结合代表它是函数指针,同样需要参数时,我们可以往里面放参数类型,最后返回值时int型。

函数指针里放的是函数的地址,数组名其实也是函数的地址,区别在于函数指针可以放不同的函数地址,而函数只能不同的参数。

2.4.1函数指针的使用

这里我们可以使用p直接来调用函数,也可以用*p来调用函数,输出的结果都是函数的结果。

例题

// 代码 1
( * ( void ( * )()) 0 )();

 

 第一个代码,我们要逐层分析,紫色层代表强制类型转化,蓝色层代表0为指针,黄色层代表函数名为0的函数指针。

2.5函数指针数组

函数指针数组:指向函数的指针的数组,,本质为数组,数组元素为指针,指针指向函数。

int (*p[10])();
这里p先和【10】进行结合,即代表本质为数组,
然后和*结合代表它是指针,
后面的括号说它是函数指针数组。

2.5.1函数指针数组的使用

这里是一个加减乘除计算器的代码:整数的加减乘除计算器 · 风夏/C语言进阶 - 码云 - 开源中国 (gitee.com)

#include <stdio.h>
int add(int a, int b) 
{  return a + b; }
int sub(int a, int b) 
{  return a - b; }
int mul(int a, int b) 
{  return a*b; }
int div(int a, int b)
{  return a / b; }
int main()
{

     int x, y;
     int input = 1;
     int ret = 0;
     int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; 
     while (input)
     {
          printf( "*************************\n" );
          printf( " 1:add           2:sub \n" );
          printf( " 3:mul           4:div \n" );
          printf( "*************************\n" );
          printf( "请选择:" );
      scanf( "%d", &input);
          if ((input <= 4 && input >= 1))
         {
          printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = (*p[input])(x, y);
         }
          else
               printf( "输入有误\n" );
          printf( "ret = %d\n", ret);
     }
      return 0; }

其中它(如图)为函数指针数组,数组元素为0,add,sub,mul,div.

当我们使用这个数组时,只需改变参数即可。如图

2.6指向函数指针数组的指针 

定义:指向函数指针数组的指针。本质为指针,指向的内容为函数指针数组。

2.6.1使用

我们把上题计算器中一些代码更改即变为指向函数指针数组的指针。

2.7回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针作为作为参数传递给另一个函数,当这个指针被用来其所指的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是当特定的事件或条件发生时由另一方调用的,用于对该事件或条件进行相应。

这里我们使用快速排序qsort,来说明回调函数。

在这个实例中qsort就是通过指针,来调用int_cmp,同时int_cmp是作为qsort函数参数的存在。


总结

这里共讲述啦7种函数指针的类型,即字符指针、数组指针、指针数组、函数指针、函数指针数组、指向函数指针数组的指针、回调函数。

    希望大家多多理解、学习,希望大家取得进步。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值