C语言进阶指针(对指针的深入探讨)

目录

文章目录

前言

一、字符指针

二、数组指针

三、函数指针

四、函数指针数组

五、函数指针数组指针

六、回调函数

总结


前言

指针的主题,我们在上一篇已经接触过了,我们知道了指针的概念:

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4. 指针的运算。

 这一篇,我们继续探讨指针的高级主题。


一、字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char* 。

一般使用: 

int main()
{
    char ch = 'w';
    char *pc = &ch;
    *pc = 'w';

    return 0;
}

还有一种使用方式如下:

int main()
{
    const char* pstr = "hello world";
    printf("%s\n", pstr);

    return 0;
}

代码 const char* pstr = "hello world";特别容易让我们以为是把字符串 hello world放到字符指针 pstr 里了,但是本质是把字符串 hello world. 首字符的地址放到了pstr中。

 

二、数组指针

数组指针是指向数组类型数据的指针变量。在C语言中,数组名可以作为指向数组首元素的指针常量,因此数组指针可以直接指向数组。例如:

int arr[5] = {1, 2, 3, 4, 5};
int (*ptr)[5] = &arr;

上面的代码中,ptr就是一个指向整型数组arr的指针,(*ptr)[5]表示一个含有5个元素的整型数组。&arr表示整个数组的地址,因此ptr指向了整个数组。

数组指针也可以通过指针运算来访问数组中的元素,例如:

int arr[5] = {1, 2, 3, 4, 5};
int (*ptr)[5] = &arr;
printf("%d\n", (*ptr)[1]);

上面的代码中,(*ptr)[1]表示指针ptr所指向的整型数组中的第二个元素,即整数2。

如果数组名已经作为指针使用,可以直接将它赋值给一个数组指针,例如:

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
int (*ptr)[5] = (int (*)[5])p;

上面的代码中,将指向整型的指针p赋值给一个指向含有5个元素的整型数组的指针ptr,需要将指针类型进行强制转换。

三、函数指针

函数指针是指向函数的指针。在C语言中,函数名也可以被看作是一个地址,指向函数的入口点。因此,可以定义一个指向特定函数的指针,以便在代码中动态地引用该函数。

函数指针的语法格式为:

返回类型 (*指针变量名)(参数列表)

其中,返回类型表示函数返回值的数据类型,参数列表表示函数的参数类型和顺序,用逗号分隔。例如:

#include <stdio.h>

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

int main()
{
    int (*pFunc)(int, int) = add; // 声明并初始化一个指向函数add的指针变量pFunc
    int result = pFunc(1, 2); // 调用add函数,结果为3

    return 0;
}

在上面的示例中,声明并初始化了一个指向add函数的指针变量pFunc,并通过指针变量调用了add函数,并将结果保存到变量result中。

函数指针还可以用于实现函数回调机制,即将函数指针作为参数传递给其他函数,让被调用函数可以调用传递进来的函数指针,从而实现回调功能。

四、函数指针数组

函数指针数组是一个数组,其中每个元素都是一个函数指针。函数指针数组可以用于存储多个函数指针,以便在程序中动态地引用这些函数。

函数指针数组的语法格式为:

返回类型 (*指针数组名[数组长度])(参数列表)

其中,返回类型表示函数返回值的数据类型,参数列表表示函数的参数类型和顺序,用逗号分隔。例如:

#include <stdio.h>

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

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

int main()
{
    int (*pFuncArr[2])(int, int) = { add, sub }; // 声明并初始化一个函数指针数组,包含指向add和sub函数的指针

    int result1 = pFuncArr[0](1, 2); // 调用add函数,结果为3
    int result2 = pFuncArr[1](1, 2); // 调用sub函数,结果为-1

    return 0;
}

在上面的示例中,声明并初始化了一个包含2个元素的函数指针数组pFuncArr,其中第一个元素指向函数add,第二个元素指向函数sub。然后使用函数指针数组分别调用了这两个函数,并将结果保存到变量result1result2中。

函数指针数组也可以用于实现函数回调机制,即将函数指针数组作为参数传递给其他函数,让被调用函数可以根据需要调用指定的函数指针,从而实现回调功能。

五、函数指针数组指针

函数指针数组指针是指一个指向数组,这个数组中的每个元素都是函数指针的指针。这个数组的每个元素都指向一个函数,它们具有相同的参数类型和返回类型。

下面是一个函数指针数组指针的例子:

#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }

int main()
{
	int (*funcPtrArr[3])(int, int) = { add, subtract, multiply };
	int (*(*funcPtrArrPtr)[3])(int, int) = &funcPtrArr;

	printf("%d\n", (*funcPtrArr[0])(1, 2)); // 输出 3
	printf("%d\n", (*funcPtrArr[1])(3, 1)); // 输出 2
	printf("%d\n", (*(*funcPtrArrPtr)[2])(2, 3)); // 输出 6

	return 0;
}

在上面的例子中,我们定义了一个包含3个函数指针的函数指针数组funcPtrArr,每个指针指向一个具有两个int类型参数和返回值的函数。然后我们定义了一个指向funcPtrArr的指针funcPtrArrPtr,并初始化它。最后,我们通过使用指针解引用操作符*来访问和调用函数指针。

注意,我们使用funcPtrArr[0]来访问数组的第一个元素,而使用(*funcPtrArrPtr)[2]来访问数组的第三个元素。这是因为,当我们想要访问函数指针数组指针中数组元素的时候,需要先解引用指向数组的指针,然后再用索引访问数组元素。

六、回调函数

回调函数就是一个被作为参数传递的函数。回调函数也可以说是一种机制,即当一个函数被调用时,它将另一个函数作为参数传递给它,并且在执行过程中调用或“回调”该函数。回调函数可以让我们编写可重用代码,因为该代码可以由其他用户编写的代码通过回调函数来调用。回调函数常用于事件驱动的程序设计中。

下面是一个简单的示例,演示如何使用回调函数:

#include <stdio.h>

void ForEach(int arr[], int size, void (*callback)(int))
{
    for (int i = 0; i < size; i++) {
        callback(arr[i]);
    }
}

void Print(int n)
{
    printf("%d ", n);
}

int main()
{
    int arr[] = { 1, 2, 3, 4, 5 };
    int size = sizeof(arr) / sizeof(arr[0]);
    ForEach(arr, size, Print); // 将Print函数作为参数传递给ForEach函数

    return 0;
}

在上述示例中,定义了一个名为ForEach的函数,它接受一个整数数组、数组大小和一个指向回调函数的指针作为参数。该函数遍历整个数组,并在处理每个元素时调用回调函数。另外,还定义了一个名为Print的回调函数,它只是简单地打印它的参数。

main函数中,定义一个名为arr的整数数组并初始化,然后根据数组大小调用ForEach函数,并将Print作为回调函数的参数传递。ForEach函数遍历整个数组,并依次调用回调函数Print,输出每个元素的值。

回调函数使程序设计更加灵活和可扩展,通过使用回调函数,我们可以使程序模块化和复用程度提高,同时增加程序的可读性和可维护性。


总结

本文是对指针的深入介绍,主要让我们对指针有进一步的了解。

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月亮有痕迹诶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值