C语言-指针详解(万字笔记,代码实例加输出,从入门到精通)

C语言指针详解:从入门到精通

目录

  1. 指针的基本概念
  2. 指针的声明与初始化
  3. 指针运算符
  4. 指针与数组
  5. 指针与函数
  6. 多级指针
  7. 动态内存分配
  8. 函数指针
  9. 高级指针应用

1. 指针的基本概念

什么是指针?

指针是一个变量,其值为另一个变量的内存地址。

核心概念:

  • 每个变量都有内存地址
  • 指针存储的是地址,而不是值
  • 通过指针可以间接访问和修改变量的值

指针是编程中的一个核心概念,特别是在底层语言如 C 或 C++ 中。它本质上是一个变量,但其值不是直接的数据,而是另一个变量在内存中的地址。这意味着指针“指向”内存中的某个位置,从而允许间接访问或操作该位置存储的数据。

核心特点
基本定义:指针是一个变量,其值为另一个变量的内存地址。例如,如果有一个变量 int x = 10;,那么一个指针 int *p; 可以存储 x 的地址,如 p = &x;。这里,&x 表示 x 的地址值(如 0 x 7 f f e e 000 0x7ffee000 0x7ffee000)。
作用:指针提供了一种高效的内存管理方式,常用于动态内存分配、数组操作、函数参数传递等场景。它减少了数据复制开销,但使用不当可能导致错误。
解引用:通过指针访问实际数据时,需要使用解引用运算符(如 *p)。例如,如果 p 指向 x,那么 *p = 20; 会将 x 的值改为 20。

#include <stdio.h>

int main() {
    int var = 42;
    
    printf("变量var的值: %d\n", var);
    printf("变量var的地址: %p\n", &var);
    
    return 0;
}

输出:

变量var的值: 42
变量var的地址: 0x7ffd4f4a5a4c

2. 指针的声明与初始化

2.1 指针声明

#include <stdio.h>

int main() {
    int num = 100;
    float f = 3.14;
    char c = 'A';
    
    // 指针声明
    int *int_ptr;      // 指向整型的指针
    float *float_ptr;  // 指向浮点型的指针
    char *char_ptr;    // 指向字符型的指针
    
    // 指针初始化
    int_ptr = &num;
    float_ptr = &f;
    char_ptr = &c;
    
    printf("变量值: num=%d, f=%.2f, c=%c\n", num, f, c);
    printf("变量地址: &num=%p, &f=%p, &c=%p\n", &num, &f, &c);
    printf("指针值: int_ptr=%p, float_ptr=%p, char_ptr=%p\n", 
           int_ptr, float_ptr, char_ptr);
    
    return 0;
}

输出:

变量值: num=100, f=3.14, c=A
变量地址: &num=0x7ffd4f4a5a4c, &f=0x7ffd4f4a5a50, &c=0x7ffd4f4a5a4b
指针值: int_ptr=0x7ffd4f4a5a4c, float_ptr=0x7ffd4f4a5a50, char_ptr=0x7ffd4f4a5a4b

2.2 空指针和野指针

#include <stdio.h>

int main() {
    // 空指针
    int *null_ptr = NULL;
    
    // 未初始化的指针(野指针)- 危险!
    int *wild_ptr;
    
    // 正确的指针初始化
    int value = 50;
    int *valid_ptr = &value;
    
    printf("空指针: %p\n", null_ptr);
    printf("未初始化指针: %p\n", wild_ptr);  // 随机值
    printf("有效指针: %p\n", valid_ptr);
    
    // 检查空指针
    if(null_ptr == NULL) {
        printf("这是一个空指针\n");
    }
    
    if(valid_ptr != NULL) {
        printf("有效指针指向的值: %d\n", *valid_ptr);
    }
    
    return 0;
}

输出:

空指针: (nil)
未初始化指针: 0x7ffd4f4a5a60
有效指针: 0x7ffd4f4a5a4c
这是一个空指针
有效指针指向的值: 50

3. 指针运算符

3.1 取地址(&)和解引用(*)

#include <stdio.h>

int main() {
    int number = 123;
    int *ptr = &number;
    
    printf("基本概念演示:\n");
    printf("变量number的值: %d\n", number);
    printf("变量number的地址: %p\n", &number);
    printf("指针ptr的值: %p\n", ptr);
    printf("指针ptr自己的地址: %p\n", &ptr);
    printf("通过ptr访问number的值: %d\n", *ptr);
    
    // 通过指针修改变量值
    printf("\n通过指针修改值:\n");
    *ptr = 456;
    printf("修改后number的值: %d\n", number);
    printf("通过ptr访问修改后的值: %d\n", *ptr);
    
    return 0;
}

输出:

基本概念演示:
变量number的值: 123
变量number的地址: 0x7ffd4f4a5a4c
指针ptr的值: 0x7ffd4f4a5a4c
指针ptr自己的地址: 0x7ffd4f4a5a50
通过ptr访问number的值: 123

通过指针修改值:
修改后number的值: 456
通过ptr访问修改后的值: 456

3.2 指针算术运算

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;  // 指向数组首元素
    
    printf("数组元素: ");
    for(int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n\n");
    
    printf("指针算术运算演示:\n");
    printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    ptr++;  // 移动到下一个整数
    printf("ptr++后: ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    ptr += 2; // 向后移动两个整数
    printf("ptr+=2后: ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    ptr--;  // 向前移动一个整数
    printf("ptr--后: ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    // 指针相减
    int *ptr1 = &arr[1];
    int *ptr2 = &arr[4];
    printf("\n指针相减:\n");
    printf("ptr2 - ptr1 = %ld (元素个数)\n", ptr2 - ptr1);
    
    return 0;
}

输出:

数组元素: 10 20 30 40 50 

指针算术运算演示:
ptr = 0x7ffd4f4a5a50, *ptr = 10
ptr++后: ptr = 0x7ffd4f4a5a54, *ptr = 20
ptr+=2后: ptr = 0x7ffd4f4a5a5c, *ptr = 40
ptr--后: ptr = 0x7ffd4f4a5a58, *ptr = 30

指针相减:
ptr2 - ptr1 = 3 (元素个数)

4. 指针与数组

4.1 数组名作为指针

#include <stdio.h>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    
    printf("数组名就是指针的证明:\n");
    printf("numbers = %p\n", numbers);
    printf("&numbers[0] = %p\n", &numbers[0]);
    printf("两者相等: %s\n", numbers == &numbers[0] ? "是" : "否");
    
    printf("\n通过不同方式访问数组:\n");
    for(int i = 0; i < 5; i++) {
        printf("numbers[%d] = %d, *(numbers + %d) = %d\n", 
               i, numbers[i], i, *(numbers + i));
    }
    
    printf("\n指针遍历数组:\n");
    int *ptr = numbers;
    for(int i = 0; i < 5; i++) {
        printf("ptr[%d] = %d, *ptr = %d\n", i, ptr[i], *ptr);
        ptr++;  // 移动到下一个元素
    }
    
    return 0;
}

输出:

数组名就是指针的证明:
numbers = 0x7ffd4f4a5a50
&numbers[0] = 0x7ffd4f4a5a50
两者相等: 是

通过不同方式访问数组:
numbers[0] = 1, *(numbers + 0) = 1
numbers[1] = 2, *(numbers + 1) = 2
numbers[2] = 3, *(numbers + 2) = 3
numbers[3] = 4, *(numbers + 3) = 4
numbers[4] = 5, *(numbers + 4) = 5

指针遍历数组:
ptr[0] = 1, *ptr = 1
ptr[1] = 2, *ptr = 2
ptr[2] = 3, *ptr = 3
ptr[3] = 4, *ptr = 4
ptr[4] = 5, *ptr = 5

4.2 指针数组 vs 数组指针

#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 30;
    
    // 指针数组:存储指针的数组
    int *ptr_array[3] = {&a, &b, &c};
    
    // 数组指针:指向数组的指针
    int arr[3] = {100, 200, 300};
    int (*array_ptr)[3] = &arr;
    
    printf("指针数组演示:\n");
    for(int i = 0; i < 3; i++) {
        printf("ptr_array[%d] = %p, *ptr_array[%d] = %d\n", 
               i, ptr_array[i], i, *ptr_array[i]);
    }
    
    printf("\n数组指针演示:\n");
    printf("array_ptr = %p\n", array_ptr);
    printf("*array_ptr = %p\n", *array_ptr);
    printf("(*array_ptr)[0] = %d\n", (*array_ptr)[0]);
    printf("(*array_ptr)[1] = %d\n", (*array_ptr)[1]);
    
    // 通过数组指针访问元素
    printf("\n通过数组指针遍历:\n");
    for(int i = 0; i < 3; i++) {
        printf("(*array_ptr)[%d] = %d\n", i, (*array_ptr)[i]);
    }
    
    return 0;
}

输出:

指针数组演示:
ptr_array[0] = 0x7ffd4f4a5a4c, *ptr_array[0] = 10
ptr_array[1] = 0x7ffd4f4a5a50, *ptr_array[1] = 20
ptr_array[2] = 0x7ffd4f4a5a54, *ptr_array[2] = 30

数组指针演示:
array_ptr = 0x7ffd4f4a5a58
*array_ptr = 0x7ffd4f4a5a58
(*array_ptr)[0] = 100
(*array_ptr)[1] = 200

通过数组指针遍历:
(*array_ptr)[0] = 100
(*array_ptr)[1] = 200
(*array_ptr)[2] = 300

5. 指针与函数

5.1 指针作为函数参数

#include <stdio.h>

// 传值调用
void swap_by_value(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    printf("函数内交换: a=%d, b=%d\n", a, b);
}

// 传址调用
void swap_by_reference(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
    printf("函数内交换: *a=%d, *b=%d\n", *a, *b);
}

// 通过指针返回多个值
void calculate(int a, int b, int *sum, int *product) {
    *sum = a + b;
    *product = a * b;
}

int main() {
    int x = 5, y = 10;
    
    printf("传值调用演示:\n");
    printf("交换前: x=%d, y=%d\n", x, y);
    swap_by_value(x, y);
    printf("交换后: x=%d, y=%d\n", x, y);
    
    printf("\n传址调用演示:\n");
    printf("交换前: x=%d, y=%d\n", x, y);
    swap_by_reference(&x, &y);
    printf("交换后: x=%d, y=%d\n", x, y);
    
    printf("\n返回多个值演示:\n");
    int s, p;
    calculate(4, 5, &s, &p);
    printf("和: %d, 积: %d\n", s, p);
    
    return 0;
}

输出:

传值调用演示:
交换前: x=5, y=10
函数内交换: a=10, b=5
交换后: x=5, y=10

传址调用演示:
交换前: x=5, y=10
函数内交换: *a=10, *b=5
交换后: x=10, y=5

返回多个值演示:
和: 9, 积: 20

5.2 返回指针的函数

#include <stdio.h>

// 返回较大值的指针
int* find_max(int *a, int *b) {
    return (*a > *b) ? a : b;
}

// 危险:返回局部变量的地址
int* dangerous_function() {
    int local_var = 100;
    return &local_var;  // 错误!局部变量在函数结束后销毁
}

// 安全:返回静态变量的地址
int* safe_function() {
    static int static_var = 200;
    return &static_var;  // 正确:静态变量在程序结束时才销毁
}

int main() {
    int num1 = 25, num2 = 40;
    
    printf("返回较大值的指针:\n");
    int *max_ptr = find_max(&num1, &num2);
    printf("较大的值是: %d\n", *max_ptr);
    
    printf("\n安全返回指针:\n");
    int *safe_ptr = safe_function();
    printf("安全返回的值: %d\n", *safe_ptr);
    
    // 危险示例(注释掉以避免未定义行为)
    // int *danger_ptr = dangerous_function();
    // printf("危险返回的值: %d\n", *danger_ptr); // 未定义行为
    
    return 0;
}

输出:

返回较大值的指针:
较大的值是: 40

安全返回指针:
安全返回的值: 200

6. 多级指针

6.1 二级指针

#include <stdio.h>

int main() {
    int value = 100;
    int *ptr = &value;
    int **pptr = &ptr;  // 指向指针的指针
    
    printf("多级指针演示:\n");
    printf("value = %d, 地址 = %p\n", value, &value);
    printf("ptr = %p, *ptr = %d, 地址 = %p\n", ptr, *ptr, &ptr);
    printf("pptr = %p, *pptr = %p, **pptr = %d\n", pptr, *pptr, **pptr);
    
    // 通过二级指针修改变量值
    printf("\n通过二级指针修改值:\n");
    **pptr = 200;
    printf("修改后 value = %d\n", value);
    printf("**pptr = %d\n", **pptr);
    
    // 二级指针的实际应用
    printf("\n二级指针应用:\n");
    char *names[] = {"Alice", "Bob", "Charlie"};
    char **name_ptr = names;
    
    for(int i = 0; i < 3; i++) {
        printf("names[%d] = %s\n", i, names[i]);
        printf("*(name_ptr + %d) = %s\n", i, *(name_ptr + i));
    }
    
    return 0;
}

输出:

多级指针演示:
value = 100, 地址 = 0x7ffd4f4a5a4c
ptr = 0x7ffd4f4a5a4c, *ptr = 100, 地址 = 0x7ffd4f4a5a50
pptr = 0x7ffd4f4a5a50, *pptr = 0x7ffd4f4a5a4c, **pptr = 100

通过二级指针修改值:
修改后 value = 200
**pptr = 200

二级指针应用:
names[0] = Alice
*(name_ptr + 0) = Alice
names[1] = Bob
*(name_ptr + 1) = Bob
names[2] = Charlie
*(name_ptr + 2) = Charlie

7. 动态内存分配

7.1 malloc, calloc, realloc, free

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

int main() {
    int size;
    
    printf("请输入数组大小: ");
    scanf("%d", &size);
    
    // 使用malloc分配内存(未初始化)
    int *arr1 = (int*)malloc(size * sizeof(int));
    if(arr1 == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    
    // 使用calloc分配内存(初始化为0)
    int *arr2 = (int*)calloc(size, sizeof(int));
    if(arr2 == NULL) {
        printf("内存分配失败!\n");
        free(arr1);
        return 1;
    }
    
    printf("malloc分配的内容(未初始化): ");
    for(int i = 0; i < size; i++) {
        printf("%d ", arr1[i]);  // 可能是随机值
    }
    printf("\n");
    
    printf("calloc分配的内容(初始化为0): ");
    for(int i = 0; i < size; i++) {
        printf("%d ", arr2[i]);
    }
    printf("\n");
    
    // 初始化arr1
    for(int i = 0; i < size; i++) {
        arr1[i] = (i + 1) * 10;
    }
    
    printf("初始化后arr1: ");
    for(int i = 0; i < size; i++) {
        printf("%d ", arr1[i]);
    }
    printf("\n");
    
    // 重新调整arr1的大小
    int new_size;
    printf("请输入新的数组大小: ");
    scanf("%d", &new_size);
    
    int *temp = (int*)realloc(arr1, new_size * sizeof(int));
    if(temp == NULL) {
        printf("内存重新分配失败!\n");
    } else {
        arr1 = temp;
        
        // 初始化新增的元素
        for(int i = size; i < new_size; i++) {
            arr1[i] = (i + 1) * 5;
        }
        
        printf("调整大小后arr1: ");
        for(int i = 0; i < new_size; i++) {
            printf("%d ", arr1[i]);
        }
        printf("\n");
    }
    
    // 释放内存
    free(arr1);
    free(arr2);
    
    printf("内存已释放\n");
    
    return 0;
}

输出示例:

请输入数组大小: 3
malloc分配的内容(未初始化): 0 0 0 
calloc分配的内容(初始化为0): 0 0 0 
初始化后arr1: 10 20 30 
请输入新的数组大小: 5
调整大小后arr1: 10 20 30 20 25 
内存已释放

8. 函数指针

8.1 函数指针的基本使用

#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 divide(int a, int b) { return b != 0 ? a / b : 0; }

int main() {
    // 声明函数指针
    int (*operation)(int, int);
    
    int x = 10, y = 5;
    
    printf("函数指针演示:\n");
    
    // 指向add函数
    operation = add;
    printf("%d + %d = %d\n", x, y, operation(x, y));
    
    // 指向subtract函数
    operation = subtract;
    printf("%d - %d = %d\n", x, y, operation(x, y));
    
    // 指向multiply函数
    operation = multiply;
    printf("%d * %d = %d\n", x, y, operation(x, y));
    
    // 指向divide函数
    operation = divide;
    printf("%d / %d = %d\n", x, y, operation(x, y));
    
    return 0;
}

输出:

函数指针演示:
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2

8.2 函数指针数组

#include <stdio.h>

// 数学运算函数
double add(double a, double b) { return a + b; }
double subtract(double a, double b) { return a - b; }
double multiply(double a, double b) { return a * b; }
double divide(double a, double b) { return b != 0 ? a / b : 0; }

int main() {
    // 函数指针数组
    double (*operations[4])(double, double) = {
        add, subtract, multiply, divide
    };
    
    char *operation_names[] = {"加法", "减法", "乘法", "除法"};
    double a = 12.0, b = 4.0;
    
    printf("函数指针数组演示:\n");
    for(int i = 0; i < 4; i++) {
        double result = operations[i](a, b);
        printf("%s: %.1f %c %.1f = %.1f\n", 
               operation_names[i], a, 
               (i == 0 ? '+' : (i == 1 ? '-' : (i == 2 ? '*' : '/'))), 
               b, result);
    }
    
    // 使用函数指针作为回调
    printf("\n回调函数演示:\n");
    void calculator(double x, double y, double (*op)(double, double)) {
        double result = op(x, y);
        printf("计算结果: %.1f\n", result);
    }
    
    calculator(15.0, 3.0, multiply);
    calculator(15.0, 3.0, divide);
    
    return 0;
}

输出:

函数指针数组演示:
加法: 12.0 + 4.0 = 16.0
减法: 12.0 - 4.0 = 8.0
乘法: 12.0 * 4.0 = 48.0
除法: 12.0 / 4.0 = 3.0

回调函数演示:
计算结果: 45.0
计算结果: 5.0

9. 高级指针应用

9.1 常量指针 vs 指针常量

#include <stdio.h>

int main() {
    int a = 10, b = 20;
    
    printf("常量指针 vs 指针常量:\n\n");
    
    // 常量指针:指向常量的指针
    // 指针可以改变,指向的值不能改变
    const int *ptr1 = &a;
    printf("常量指针:\n");
    printf("ptr1指向: %d\n", *ptr1);
    // *ptr1 = 30;  // 错误:不能修改指向的值
    ptr1 = &b;     // 正确:可以改变指针的指向
    printf("ptr1现在指向: %d\n", *ptr1);
    
    // 指针常量:指针本身是常量
    // 指向的值可以改变,指针不能改变
    int *const ptr2 = &a;
    printf("\n指针常量:\n");
    printf("ptr2指向: %d\n", *ptr2);
    *ptr2 = 30;    // 正确:可以修改指向的值
    printf("修改后ptr2指向: %d\n", *ptr2);
    // ptr2 = &b;  // 错误:不能改变指针的指向
    
    // 指向常量的指针常量
    const int *const ptr3 = &a;
    printf("\n指向常量的指针常量:\n");
    printf("ptr3指向: %d\n", *ptr3);
    // *ptr3 = 40;  // 错误:不能修改指向的值
    // ptr3 = &b;   // 错误:不能改变指针的指向
    
    return 0;
}

输出:

常量指针 vs 指针常量:

常量指针:
ptr1指向: 10
ptr1现在指向: 20

指针常量:
ptr2指向: 10
修改后ptr2指向: 30

指向常量的指针常量:
ptr3指向: 30

9.2 复杂指针声明解析

#include <stdio.h>

int main() {
    int arr[3] = {1, 2, 3};
    int *ptr_arr[3];  // 指针数组
    int (*array_ptr)[3]; // 数组指针
    
    // 初始化指针数组
    for(int i = 0; i < 3; i++) {
        ptr_arr[i] = &arr[i];
    }
    
    array_ptr = &arr;
    
    printf("复杂指针声明解析:\n\n");
    
    printf("int *ptr_arr[3] - 指针数组:\n");
    for(int i = 0; i < 3; i++) {
        printf("ptr_arr[%d] = %p, *ptr_arr[%d] = %d\n", 
               i, ptr_arr[i], i, *ptr_arr[i]);
    }
    
    printf("\nint (*array_ptr)[3] - 数组指针:\n");
    printf("array_ptr = %p\n", array_ptr);
    printf("*array_ptr = %p\n", *array_ptr);
    for(int i = 0; i < 3; i++) {
        printf("(*array_ptr)[%d] = %d\n", i, (*array_ptr)[i]);
    }
    
    // 函数指针的复杂声明
    printf("\n复杂函数指针:\n");
    int (*func_ptr)(int, int);  // 函数指针
    int *(*func_ptr_arr[3])(int, int);  // 函数指针数组
    
    printf("int (*func_ptr)(int, int) - 函数指针\n");
    printf("int *(*func_ptr_arr[3])(int, int) - 返回int指针的函数指针数组\n");
    
    return 0;
}

输出:

复杂指针声明解析:

int *ptr_arr[3] - 指针数组:
ptr_arr[0] = 0x7ffd4f4a5a4c, *ptr_arr[0] = 1
ptr_arr[1] = 0x7ffd4f4a5a50, *ptr_arr[1] = 2
ptr_arr[2] = 0x7ffd4f4a5a54, *ptr_arr[2] = 3

int (*array_ptr)[3] - 数组指针:
array_ptr = 0x7ffd4f4a5a4c
*array_ptr = 0x7ffd4f4a5a4c
(*array_ptr)[0] = 1
(*array_ptr)[1] = 2
(*array_ptr)[2] = 3

复杂函数指针:
int (*func_ptr)(int, int) - 函数指针
int *(*func_ptr_arr[3])(int, int) - 返回int指针的函数指针数组

9.3 实际应用:通用排序函数

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

// 通用比较函数类型
typedef int (*CompareFunction)(const void*, const void*);

// 整数比较函数
int compare_int(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

// 字符串比较函数
int compare_string(const void *a, const void *b) {
    return strcmp(*(const char**)a, *(const char**)b);
}

// 通用排序函数
void generic_sort(void *array, size_t count, size_t size, CompareFunction compare) {
    // 简单的冒泡排序实现
    for(size_t i = 0; i < count - 1; i++) {
        for(size_t j = 0; j < count - i - 1; j++) {
            void *elem1 = (char*)array + j * size;
            void *elem2 = (char*)array + (j + 1) * size;
            
            if(compare(elem1, elem2) > 0) {
                // 交换元素
                char temp[size];
                memcpy(temp, elem1, size);
                memcpy(elem1, elem2, size);
                memcpy(elem2, temp, size);
            }
        }
    }
}

int main() {
    printf("通用排序函数演示:\n\n");
    
    // 整数数组排序
    int numbers[] = {64, 34, 25, 12, 22, 11, 90};
    int num_count = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("排序前整数数组: ");
    for(int i = 0; i < num_count; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    generic_sort(numbers, num_count, sizeof(int), compare_int);
    
    printf("排序后整数数组: ");
    for(int i = 0; i < num_count; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n\n");
    
    // 字符串数组排序
    char *names[] = {"Charlie", "Alice", "Bob", "David"};
    int name_count = sizeof(names) / sizeof(names[0]);
    
    printf("排序前字符串数组: ");
    for(int i = 0; i < name_count; i++) {
        printf("%s ", names[i]);
    }
    printf("\n");
    
    generic_sort(names, name_count, sizeof(char*), compare_string);
    
    printf("排序后字符串数组: ");
    for(int i = 0; i < name_count; i++) {
        printf("%s ", names[i]);
    }
    printf("\n");
    
    return 0;
}

输出:

通用排序函数演示:

排序前整数数组: 64 34 25 12 22 11 90 
排序后整数数组: 11 12 22 25 34 64 90 

排序前字符串数组: Charlie Alice Bob David 
排序后字符串数组: Alice Bob Charlie David 

总结

关键知识点回顾:

  1. 指针基础:存储地址的变量,&取地址,*解引用
  2. 指针运算:算术运算、比较运算
  3. 指针与数组:数组名即指针,指针数组,数组指针
  4. 函数指针:指向函数的指针,支持回调
  5. 多级指针:指向指针的指针
  6. 动态内存:malloc/calloc/realloc/free
  7. 常量指针:const的不同位置含义不同

最佳实践:

  1. 总是初始化指针
  2. 检查malloc/calloc的返回值
  3. 释放内存后立即设为NULL
  4. 理解const的正确使用
  5. 避免指针越界访问
  6. 使用函数指针实现多态

常见错误:

  1. 使用未初始化的指针
  2. 访问已释放的内存
  3. 内存泄漏
  4. 数组越界
  5. 返回局部变量的地址

指针堪称C语言的核心精髓,能否驾驭指针将决定你能否成为真正的C语言高手。只要坚持实战演练,你就能灵活运用指针攻克各类编程难题!

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值