一、二级指针(指向指针的指针)
1. 基本定义
-
二级指针是指指向指针变量的指针。
-
声明形式:int **pp;
-
内存模型:
-
一级指针 int *p 存储某个 int 变量的地址。
-
二级指针 int **pp 存储 p 的地址。
-
2. 主要用途
在函数中修改外部指针变量的值
若需在函数内改变外部指针的指向(如动态分配内存并返回),需传递该指针的地址(即二级指针)。
示例:
void allocate(int **ptr) {
*ptr = (int*)malloc(sizeof(int));
}
int main() {
int *p = NULL;
allocate(&p);
free(p);
return 0;
}
指针数组的传参
指针数组的数组名即为指向第一个指针元素的指针,即二级指针。
#include <stdio.h>
void input(char **ppa[3],int len)
{
int i = 0;
for(i=0;i<len;i++)
{
gets(ppa[i]);
}
return ;
}
void output(char **ppa[3],int len)
{
int i = 0;
for(i=0;i<len;i++)
{
printf("ppa[%d]=%s\\n",i,ppa[i]);
}
return ;
}
int main(void)
{
char a[3][5]={0};
char *pa[3]={a[0],a[1],a[2]};
input(pa,3);
output(pa,3);
return 0;
}
二、void 指针(通用指针)
1. 基本特性
-
声明:void *p;
-
特点:
-
可以指向任何类型的数据。
-
不能直接进行解引用和算术运算(需强制类型转换后使用)。
-
常用于函数参数和返回值,实现通用接口。
-
2. 类型转换规则
-
其他类型指针 → void*:需要强制类型转换。
-
void* → 其他类型指针:不需要强制类型转换(但推荐显式转换以增强可读性)。
示例:
int a = 10;
void *vp = (void*)&a; // 必须转换
int *ip = vp; // 可隐式转换,建议写 (int*)vp
3. 应用场景
-
内存操作函数(如 memcpy、memset)的参数。
-
泛型数据结构的实现(如链表、队列)。
三、volatile 指针
1. 作用与意义
-
volatile 关键字告知编译器:该变量可能被程序之外的因素(如硬件、中断、其他线程)修改。
-
防止编译器进行优化(如将变量缓存到寄存器),确保每次访问都直接从内存读取。
2. 使用形式
volatile int *p; // 指向的内存内容易变
int volatile *p; // 同上
volatile int * volatile p; // 指针本身和指向内容都易变
3. 典型应用
-
硬件寄存器的访问。
-
多线程共享变量。
-
信号处理程序中的全局变量。
四、数组指针 vs 指针数组
1. 指针数组(Array of Pointers)
-
本质是数组,元素为指针。
-
声明:int *arr[5];
-
含义:定义一个包含5个 int* 类型元素的数组。
-
内存占用:若为 int*,64位系统下每个指针8字节,共 5 * 8 = 40 字节。
典型应用:字符串数组(字符指针数组)
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri"};
printf("%s\\n", days[0]); // 输出 "Mon"
指针数组实现冒泡排序
1 #include <stdio.h>
2 #include <string.h>
3
4 int main(void)
5 {
6 char a[5][32]={0};
7 char*pa[5]={a[0],a[1],a[2],a[3],a[4]};
8 int i = 0;
9 int j = 0;
10 char*tmp = {0};
11
12 for(i=0;i<5;i++)
13 {
14 gets(pa[i]);
15 }
16 for(j=0;j<4;j++)
17 {
18 for(i=0;i<4-j;i++)
19 {
20 if(strcmp(pa[i],pa[i+1])>0)
21 {
22 tmp = pa[i];
23 pa[i] = pa[i+1];
24 pa[i+1] = tmp;
25
26 }
27 }
28 }
29 for(i=0;i<5;i++)
30 {
31 printf("pa[%d]=%s\\n",i,pa[i]);
32 }
33
34 return 0;
35 }
2. 数组指针(Pointer to an Array)
-
本质是指针,指向一个数组。
-
声明:int (*p)[5];
-
含义:p 是一个指针,指向一个包含5个 int 的数组。
-
内存占用:指针本身占8字节(64位)。
典型应用:二维数组传参或操作
int a[3][4] = {0};
int (*p)[4] = a; // p 指向 a 的第一行(一个包含4个int的数组)
printf("%d\\n", p[1][2]); // 等价于 a[1][2]
3. 核心区别对比表
| 本质 | 数组 | 指针 |
| 元素/指向类型 | int* | 一个 int[5] 数组 |
| 常见用途 | 存储多个字符串或动态分配的多组数据 | 操作二维数组,尤其作为函数参数 |
| 内存大小 | 元素数 × 指针大小 | 固定为指针大小(8字节) |
4. 二维数组传参的两种方式
-
方式一:数组指针形式(推荐,明确列数)
void func(int (*p)[4], int rows);
-
方式二:退化指针形式(灵活,但丢失列信息)
void func(int *p, int rows, int cols);
今日练习
1.封装一个函数,传入a和n,计算得到对应的结果。
`` tex a = 3; n = 5; 3 + 33 + 333 + 3333 + 33333 = 37035
2.封装函数从终端接收5个字符串,封装函数从大到小对字符串排序,封装函数打印字符串排序后的结果。







