Appearance
指针进阶
本章将深入探讨指针的高级用法,包括多级指针、函数指针、指针与数组的高级应用等。
多级指针
c
/*
* 多级指针
*/
#include <stdio.h>
int main(void)
{
int num = 10;
/* 一级指针:指向普通变量 */
int *p1 = #
/* 二级指针:指向一级指针 */
int **p2 = &p1;
/* 三级指针:指向二级指针 */
int ***p3 = &p2;
printf("=== 多级指针 ===\n");
printf("num = %d\n", num);
printf("*p1 = %d\n", *p1);
printf("**p2 = %d\n", **p2);
printf("***p3 = %d\n", ***p3);
printf("\n=== 地址关系 ===\n");
printf("&num = %p\n", (void*)&num);
printf("p1 = %p\n", (void*)p1);
printf("*p2 = %p\n", (void*)*p2);
printf("**p3 = %p\n", (void*)**p3);
/* 通过多级指针修改值 */
**p2 = 20;
printf("\n通过**p2修改后: num = %d\n", num);
***p3 = 30;
printf("通过***p3修改后: num = %d\n", num);
/* 实际应用:动态二维数组 */
printf("\n=== 动态二维数组 ===\n");
int rows = 3, cols = 4;
/* 分配行指针数组 */
int **matrix = (int**)malloc(rows * sizeof(int*));
/* 分配每行 */
for (int i = 0; i < rows; i++) {
matrix[i] = (int*)malloc(cols * sizeof(int));
}
/* 初始化 */
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
}
}
/* 打印 */
printf("动态二维数组:\n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
/* 释放 */
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
return 0;
}函数指针
基本用法
c
/*
* 函数指针基础
*/
#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(void)
{
/* 声明函数指针 */
int (*operation)(int, int);
/* 指向add函数 */
operation = add;
printf("add(10, 5) = %d\n", operation(10, 5));
/* 指向subtract函数 */
operation = subtract;
printf("subtract(10, 5) = %d\n", operation(10, 5));
/* 使用typedef简化 */
typedef int (*MathOp)(int, int);
MathOp op1 = add;
MathOp op2 = multiply;
printf("\nop1(10, 5) = %d\n", op1(10, 5));
printf("op2(10, 5) = %d\n", op2(10, 5));
/* 函数指针数组 */
MathOp operations[] = {add, subtract, multiply, divide};
char *names[] = {"加", "减", "乘", "除"};
printf("\n=== 计算器 ===\n");
for (int i = 0; i < 4; i++) {
printf("10 %s 5 = %d\n", names[i], operations[i](10, 5));
}
return 0;
}回调函数
c
/*
* 回调函数
*/
#include <stdio.h>
#include <stdlib.h>
/* 比较函数类型 */
typedef int (*CompareFunc)(const void*, const void*);
/* 整数比较函数 */
int compare_int(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
/* 降序比较 */
int compare_desc(const void *a, const void *b)
{
return (*(int*)b - *(int*)a);
}
/* 使用回调函数的排序 */
void bubble_sort(void *arr, size_t count, size_t size, CompareFunc compare)
{
char *base = (char*)arr;
char *temp = (char*)malloc(size);
for (size_t i = 0; i < count - 1; i++) {
for (size_t j = 0; j < count - 1 - i; j++) {
void *a = base + j * size;
void *b = base + (j + 1) * size;
if (compare(a, b) > 0) {
/* 交换 */
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
}
}
}
free(temp);
}
/* 处理数组元素的回调 */
typedef void (*ProcessFunc)(int*);
void double_value(int *n) { *n *= 2; }
void square_value(int *n) { *n *= *n; }
void negate_value(int *n) { *n = -*n; }
void process_array(int arr[], int len, ProcessFunc process)
{
for (int i = 0; i < len; i++) {
process(&arr[i]);
}
}
int main(void)
{
int arr[] = {5, 2, 8, 1, 9, 3};
int len = sizeof(arr) / sizeof(arr[0]);
printf("原数组: ");
for (int i = 0; i < len; i++) printf("%d ", arr[i]);
/* 使用回调函数排序 */
bubble_sort(arr, len, sizeof(int), compare_int);
printf("\n升序: ");
for (int i = 0; i < len; i++) printf("%d ", arr[i]);
bubble_sort(arr, len, sizeof(int), compare_desc);
printf("\n降序: ");
for (int i = 0; i < len; i++) printf("%d ", arr[i]);
/* 使用qsort(标准库) */
int arr2[] = {5, 2, 8, 1, 9, 3};
qsort(arr2, len, sizeof(int), compare_int);
printf("\n\nqsort结果: ");
for (int i = 0; i < len; i++) printf("%d ", arr2[i]);
/* 处理数组 */
int arr3[] = {1, 2, 3, 4, 5};
printf("\n\n原数组: ");
for (int i = 0; i < 5; i++) printf("%d ", arr3[i]);
process_array(arr3, 5, double_value);
printf("\n翻倍后: ");
for (int i = 0; i < 5; i++) printf("%d ", arr3[i]);
return 0;
}函数指针作为返回值
c
/*
* 函数指针作为返回值
*/
#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; }
/* 函数指针类型 */
typedef int (*Operation)(int, int);
/* 根据操作符返回对应的函数 */
Operation get_operation(char op)
{
switch (op) {
case '+': return add;
case '-': return subtract;
case '*': return multiply;
default: return NULL;
}
}
int main(void)
{
char ops[] = {'+', '-', '*'};
for (int i = 0; i < 3; i++) {
Operation op = get_operation(ops[i]);
if (op != NULL) {
printf("10 %c 5 = %d\n", ops[i], op(10, 5));
}
}
return 0;
}指针与多维数组
c
/*
* 指针与多维数组
*/
#include <stdio.h>
int main(void)
{
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
printf("=== 二维数组的指针理解 ===\n");
/* arr 是指向第一行的指针 */
printf("arr = %p\n", (void*)arr);
printf("arr[0] = %p\n", (void*)arr[0]);
printf("&arr[0][0] = %p\n", (void*)&arr[0][0]);
/* arr + 1 指向第二行 */
printf("\narr + 1 = %p\n", (void*)(arr + 1));
printf("arr[1] = %p\n", (void*)arr[1]);
/* *(arr + 1) 是第二行的首元素地址 */
printf("\n*(arr + 1) = %p\n", (void*)*(arr + 1));
printf("&arr[1][0] = %p\n", (void*)&arr[1][0]);
/* *(*(arr + 1) + 2) 是 arr[1][2] */
printf("\n*(*(arr + 1) + 2) = %d\n", *(*(arr + 1) + 2));
printf("arr[1][2] = %d\n", arr[1][2]);
/* 使用指针遍历二维数组 */
printf("\n=== 指针遍历二维数组 ===\n");
/* 方法1:指向行的指针 */
int (*row_ptr)[4] = arr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%2d ", row_ptr[i][j]);
}
printf("\n");
}
/* 方法2:指向元素的指针 */
printf("\n");
int *elem_ptr = &arr[0][0];
for (int i = 0; i < 3 * 4; i++) {
printf("%2d ", elem_ptr[i]);
if ((i + 1) % 4 == 0) printf("\n");
}
/* 方法3:使用指针运算 */
printf("\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%2d ", *(*(arr + i) + j));
}
printf("\n");
}
return 0;
}复杂指针声明
c
/*
* 理解复杂指针声明
*/
#include <stdio.h>
/*
* 指针声明阅读规则(右左法则):
* 1. 从变量名开始
* 2. 先向右读,再向左读
* 3. 遇到括号就跳到括号内
*/
int main(void)
{
/* 简单指针 */
int *p1; /* p1是指向int的指针 */
/* 指针数组 */
int *p2[5]; /* p2是数组,包含5个指向int的指针 */
/* 数组指针 */
int (*p3)[5]; /* p3是指针,指向包含5个int的数组 */
/* 函数指针 */
int (*p4)(int); /* p4是指针,指向返回int、参数为int的函数 */
/* 函数指针数组 */
int (*p5[5])(int); /* p5是数组,包含5个函数指针 */
/* 返回指针的函数 */
int *func(int); /* func是函数,返回指向int的指针 */
/* 返回函数指针的函数 */
int (*func2(int))(int); /* func2是函数,参数为int,返回函数指针 */
/* 复杂示例 */
int (*(*p6)[5])(int); /* p6是指针,指向包含5个函数指针的数组 */
printf("复杂指针声明示例已编译通过\n");
/* 实际示例 */
int arr[5] = {1, 2, 3, 4, 5};
/* 数组指针 */
int (*arr_ptr)[5] = &arr;
printf("\n数组指针: (*arr_ptr)[0] = %d\n", (*arr_ptr)[0]);
/* 指针数组 */
int a = 1, b = 2, c = 3;
int *ptr_arr[3] = {&a, &b, &c};
printf("指针数组: *ptr_arr[0] = %d\n", *ptr_arr[0]);
/* 函数指针 */
int add(int x, int y) { return x + y; }
int (*func_ptr)(int, int) = add;
printf("函数指针: func_ptr(3, 4) = %d\n", func_ptr(3, 4));
return 0;
}指针与const
c
/*
* 指针与const的进阶用法
*/
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 20;
/* 1. 指向常量的指针 */
const int *p1 = &a;
/* *p1 = 100; */ /* 错误:不能修改指向的值 */
p1 = &b; /* 正确:可以修改指针本身 */
/* 2. 常量指针 */
int * const p2 = &a;
*p2 = 100; /* 正确:可以修改指向的值 */
/* p2 = &b; */ /* 错误:不能修改指针本身 */
/* 3. 指向常量的常量指针 */
const int * const p3 = &a;
/* *p3 = 200; */ /* 错误 */
/* p3 = &b; */ /* 错误 */
/* 实际应用 */
printf("=== 实际应用 ===\n");
/* 字符串处理函数参数 */
/* size_t strlen(const char *s); */
/* 参数是const char*,保证函数不会修改字符串 */
/* 返回常量指针 */
const int* get_constant(void);
/* 结构体成员指针 */
struct Config {
const char *name; /* 指向常量字符串 */
int * const values; /* 常量指针,始终指向同一地址 */
};
printf("const指针用法示例完成\n");
return 0;
}指针安全
c
/*
* 指针安全编程
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("=== 指针安全编程 ===\n\n");
/* 1. 初始化指针 */
int *p1 = NULL; /* 始终初始化为NULL */
/* 2. 使用前检查 */
if (p1 != NULL) {
printf("*p1 = %d\n", *p1);
} else {
printf("p1是空指针\n");
}
/* 3. 释放后置NULL */
int *p2 = (int*)malloc(sizeof(int));
if (p2 != NULL) {
*p2 = 100;
printf("分配成功: %d\n", *p2);
free(p2);
p2 = NULL; /* 释放后立即置NULL */
}
/* 4. 避免野指针 */
int *wild;
/* printf("%d", *wild); */ /* 未定义行为 */
/* 5. 避免悬空指针 */
int *dangling;
{
int local = 10;
dangling = &local;
} /* local被销毁 */
/* printf("%d", *dangling); */ /* 未定义行为 */
/* 6. 检查分配是否成功 */
int *large = (int*)malloc(1000000000000);
if (large == NULL) {
printf("大内存分配失败\n");
}
/* 7. 使用assert */
#include <assert.h>
int *p3 = (int*)malloc(sizeof(int));
assert(p3 != NULL); /* 如果为NULL,程序终止 */
free(p3);
printf("\n指针安全检查完成\n");
return 0;
}小结
本章学习了:
- 多级指针:二级指针、三级指针、动态二维数组
- 函数指针:声明、使用、回调函数、函数指针数组
- 指针与多维数组:理解二维数组的指针表示
- 复杂指针声明:右左法则解读
- 指针与const:const的各种组合用法
- 指针安全:避免野指针、悬空指针、内存泄漏
掌握指针进阶知识,可以更好地理解和使用C语言的强大功能。
