自学内容网 自学内容网

高阶C语言|探索指针的根源之目(进阶指针)

💬 欢迎讨论:在阅读过程中有任何疑问,欢迎在评论区留言,我们一起交流学习!

👍 点赞、收藏与分享:如果你觉得这篇文章对你有帮助,记得点赞、收藏,并分享给更多对指针感兴趣的朋友!

在学习这篇文章之前,强烈建议先学习初阶指针哦~
传送门呈上~
初探C语言|一篇文章让你拿捏指针(初阶指针)

前言

C语言的指针被视为一项强大但复杂的工具,它允许程序直接操作内存,提高程序的灵活性和效率。虽然指针的基础用法很多人已经掌握,但更深入的理解能够帮助开发者解决更复杂的编程问题。本文将详细探讨C语言中一些进阶的指针概念,包括字符指针、数组指针、指针数组、函数指针、指向函数指针数组的指针等,并通过示例深入讲解它们的用法和应用场景。

1. 字符指针(char*

字符指针是指向单个字符或字符串的指针,它在处理字符串和字符数组时特别有用。在C语言中,字符串是一个字符数组,字符指针通常用于访问字符串的首地址。

1.1 字符串常量与指针

在C语言中,字符串本质上是字符的数组,并且以\0结尾,表示字符串的结束。字符指针指向的是数组的首元素。例如:

const char* pstr = "Hello, World!";

pstr是一个字符指针,指向常量字符串的首字符。需要注意的是,pstr存储的是字符串的内存地址,而不是字符串本身。

1.2 字符指针的使用

通过字符指针,我们可以访问字符串中的每个字符:

#include <stdio.h>

int main() {
    const char* pstr = "Hello, World!";
    while (*pstr != '\0') {
        printf("%c ", *pstr);
        pstr++;  // 指针自增,访问下一个字符
    }
    return 0;
}

输出:

H e l l o ,   W o r l d !

2. 数组指针与指针数组

在C语言中,数组与指针之间有紧密的关系。我们经常需要使用指针来处理数组。理解数组指针指针数组的区别对于编写高效的代码至关重要。

2.1 指针数组

指针数组是一个数组,其中每个元素都是指向某种数据类型的指针。通常,用指针数组来存储多个指向不同数据的指针。

int* arr[10];  // 定义了一个包含10个指针的数组

每个元素都是一个指向整数的指针,可以通过数组索引访问指针:

#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 30;
    int* arr[3] = {&a, &b, &c};
    
    for (int i = 0; i < 3; i++) {
        printf("Value at arr[%d]: %d\n", i, *arr[i]);
    }
    
    return 0;
}

输出:

Value at arr[0]: 10
Value at arr[1]: 20
Value at arr[2]: 30
2.2 数组指针

数组指针是一个指向整个数组的指针。它与指针数组的关键区别在于,数组指针指向的是整个数组,而指针数组指向的是数组中的各个元素。

例如,二维数组可以通过数组指针传递给函数:

int (*arr)[10];  // 指向包含10个整数的数组的指针
#include <stdio.h>

void print_array(int (*arr)[3]) {
    for (int i = 0; i < 3; i++) {
        printf("%d ", (*arr)[i]);
    }
    printf("\n");
}

int main() {
    int arr[3] = {1, 2, 3};
    print_array(&arr);
    return 0;
}

3. 数组与指针传参

在C语言中,当我们将数组作为参数传递给函数时,传递的实际上是数组的首地址。通过指针访问数组,可以方便地进行数组的操作。

3.1 一维数组传参
void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

由于数组本质上是指针类型,arr[]等价于int* arr。这样,数组的所有元素都可以通过指针进行访问。

3.2 二维数组传参

二维数组在传递时,需要指定第二维的大小,这样才能正确计算内存偏移量。例如:

void print_2d_array(int arr[3][4]) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

4. 函数指针(function pointer

函数指针是指向函数的指针,能够存储一个函数的地址。通过函数指针,我们可以实现动态调用函数,这对于回调函数和事件驱动的编程非常有用。

4.1 函数指针的基本用法

定义一个函数指针并通过它调用函数:

#include <stdio.h>

void test(int a) {
    printf("Test: %d\n", a);
}

int main() {
    void (*func_ptr)(int) = test;
    func_ptr(10);  // 通过函数指针调用 test 函数
    return 0;
}
4.2 使用函数指针数组

函数指针数组是一个数组,其中每个元素都是一个指向函数的指针。常用于实现多态性或函数的动态调度。

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 (*ops[4])(int, int) = {add, sub, mul, div};
    int x = 10, y = 5;
    
    printf("Addition: %d\n", ops[0](x, y));
    printf("Subtraction: %d\n", ops[1](x, y));
    printf("Multiplication: %d\n", ops[2](x, y));
    printf("Division: %d\n", ops[3](x, y));
    return 0;
}

输出:

Addition: 15
Subtraction: 5
Multiplication: 50
Division: 2

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

指向函数指针数组的指针是一种较为复杂的结构,允许通过指针访问一个存储函数指针的数组。它在复杂的回调机制或动态函数调用中非常有用。

int (*(*pf)[10])(int, int);

这种复杂的结构通常用于处理多个回调函数或多态调用。

6. 回调函数(Callback Function)

回调函数是通过函数指针传递的函数,它通常在某个事件发生时被调用。在C语言中,回调函数广泛用于处理异步事件或某些特定条件的处理。

例如,标准库中的qsort函数就是一个典型的回调函数应用场景:

#include <stdio.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    int arr[] = {5, 3, 8, 1, 2};
    qsort(arr, 5, sizeof(int), compare);
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

在这个例子中,compare函数作为回调函数传递给qsort,用于比较数组元素,从而完成排序。

完~


原文地址:https://blog.csdn.net/Surplus886/article/details/145118733

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!