G
N
I
D
A
O
L

C/C++的指针用法总结

1. 普通指针

定义声明

声明 类型 含义
int a int 整型变量
int *a int * 一级指针)指向整型变量的指针
int **a int *(*) 二级指针)指向一个指向整型变量指针的指针
int *(*a) int *(*) 二级指针)指向一个指向整型变量指针的指针

申请与释放空间

  • C 语言:
// 申请空间
int *p = (int *) malloc(sizeof(int));

// 释放空间
free(p);
  • C++:
// 申请空间
int *p = new int;

// 释放空间
delete p;

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

(已定义int aint *p

语句/表达式 含义
a = 2; 2 赋值给 a
&a 取得 a 的地址
p = &a; a 的地址赋值给指针 p
*p 指针 p 所指向的内容
*p = 2; 2 赋值给 p 指向的内容(即 a)
&p 取得指针 p 的地址
语句/表达式 含义
p++ p 地址自增一个 int 长度(4 字节)
++p p 地址自增一个 int 长度(4 字节)
*p++ 先获取 p 所指向的内容,p 地址再自增一个 int 长度(4 字节)(*和++同优先级,结合方向为从右往左
*(p++) 先获取 p 所指向的内容,p 地址再自增一个 int 长度(4 字节)
++*p p 地址先自增一个 int 长度(4 字节),再获取 p 所指向的内容(*和++同优先级,结合方向为从右往左
*(++p) p 地址先自增一个 int 长度(4 字节),再获取 p 所指向的内容
(*p)++ p 指向的内容自增
++(*p) p 指向的内容自增
语句/表达式 含义
(int*)0x1234 将 0x1234 强制转换为地址(绝对地址
p = (int*)0x1234; p 指向地址 0x1234
*((int*)0x1234) = 2; 往地址 0x1234 处写入 2(嵌入式常用)
*(int*)(0x1234) = 2; 往地址 0x1234 处写入 2(嵌入式常用)
*((int* const)0x1234) = 2; 往地址 0x1234 处写入 2(嵌入式常用)
*(int* const)(0x1234) = 2; 往地址 0x1234 处写入 2(嵌入式常用)
*((int*)p) = 2; 往指针 p 所指向的内容写入 2
*(int*)p = 2; 往指针 p 所指向的内容写入 2

作函数形参

语句/表达式 含义
void fun (int a, int *b) 形参 b 为整型指针

2. 一维数组

定义声明

声明 类型 含义
int a[10] int [10] 有 10 个整型变量的数组
int *a[10] int *[10] 指针数组)有 10 个整型变量指针的数组
int (*a)[10] int (*)[10] 数组指针)指向有 10 个整型数组的指针

提示:如何记忆指针数组和数组指针的区别?

  • X 型数组(数组里放的是 X 类型的数据):整型数组、浮点型数组、字符型数组、指针数组
  • X 型指针(指针指向 X 类型的数据):整型指针、浮点型指针、字符型指针、数组指针、函数指针

申请与释放空间

  • C 语言:
// 申请空间
int *p = (int *) malloc(10 * sizeof(int));

// 释放空间
free(p);
  • C++:
// 申请空间
int *p = new int[10];

// 释放空间
delete []p;

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

(已定义int a[10]int *p1, *p2

语句/表达式 含义
a a[0] 地址
&a 取得 a[0] 地址
&a[0] 取得 a[0] 地址
&a[5] 取得 a[5] 地址
a + 5 a[5] 地址
*(a + 5) a[5] 内容
*(a + 5) = 2; 2 赋值给 a[5]
p1 = a; p1 指向 a[0] 地址
p1 = &a; p1 指向 a[0] 地址
p1 = &a[0]; p1 指向 a[0] 地址
p2 = &a[5]; p2 指向 a[5] 地址
*p1 = 0; 0 赋值给 p1 指向的内容即 a[0]
*p2 = 5; 5 赋值给 p2 指向的内容即 a[5]
p1 + p2 错误写法,指针不可相加
p1 - p2 p1 和 p2 之间相差了多少个 int 地址单元,值为 5(1 个 int 单元是 4 字节长度)

作函数形参

语句/表达式 含义
void fun (int a, int b[10]) 形参 b 显式给出数组长度,必须将长度为 10 的整型数组作为实参
void fun (int a, int b[]) 整型指针 b,任意整型变量都可作为实参
void fun (int a, int *b) 整型指针 b,任意整型变量都可作为实参

3. 二维数组

定义声明

声明 类型 含义
int a[4][10] int [4][10]int (*)[10] 一个 4 行 10 列的二维数组,注意类型不是二级指针
int a[][10] = {0,1,2,3,4,5,6,7,8,9,10,11} int [][10] 当没有定义行时,必须至少赋值一个数据,这是一个 2 行 10 列的二维数组

提示:将int a[4][10]视为一个存放了 4 个指针的数组,这些指针都指向有 10 个元素的不同数组。

下标 内容
(*a)[0] 指向 10 个元素的数组的指针
(*a)[1] 指向 10 个元素的数组的指针
(*a)[2] 指向 10 个元素的数组的指针
(*a)[3] 指向 10 个元素的数组的指针

申请与释放空间

  • C 语言:

方法一:内存可能不连续

// 申请空间
int **p = (int **) malloc(4 * sizeof(int *)); // 动态申请 4 行二维数组
for (int i = 0; i < 4; i++){                  // 每行申请 10 个长度的数组
    p[i] = (int *) malloc(10 * sizeof(int));
}

// 释放空间
for (int i = 0; i < 4; i++){
    free(p[i]);
}
free(p);

方法二:内存连续

// 申请空间
int **p = (int **) malloc(4 * sizeof(int*)); // 动态申请 4 行二维数组
p[0] = (int *) malloc(4 * 10 * sizeof(int)); // 每行申请 10 个长度的数组

// 释放空间
free(p);
  • C++:

方法一:内存可能不连续

// 申请空间
int **p = new int*[4];       // 动态申请 4 行二维数组
for (int i = 0; i < 4; i++){ // 每行申请 10 个长度的数组
    p[i] = new int[10];
}

// 释放空间
for (int i = 0; i < 4; i++){
    delete []p[i];
}
delete []p;

方法二:内存连续

// 申请空间
int **p = new int*[4];  // 动态申请 4 行二维数组
p[0] = new int[4 * 10]; // 每行申请 10 个长度的数组

// 释放空间
delete []p;

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

语句/表达式 含义
a a[0][0] 地址,或 0 行起始地址
*a a[0][0] 地址,或 0 行起始地址
*(a + 0) a[0][0] 地址,或 0 行起始地址
a[0] a[0][0] 地址,或 0 行起始地址
&a 取得 a[0][0] 地址,或 0 行起始地址
&a[0] 取得 a[0][0] 地址,或 0 行起始地址
&a[0][0] 取得 a[0][0] 地址
a[0][0] a[0][0] 的值
*a[0] a[0][0] 的值
*(*(a + 0) + 0) a[0][0] 的值
**a a[0][0] 的值
语句/表达式 含义
a + 3 a[3][0] 地址,或 3 行起始地址
*(a + 3) a[3][0] 地址,或 3 行起始地址
a[3] a[3][0] 地址,或 3 行起始地址
&a[3] 取得 a[3][0] 地址,或 3 行起始地址
&a[3][0] 取得 a[3][0] 地址
a[3][0] a[3][0] 的值
*a[3] a[3][0] 的值
*(*(a + 3) + 0) a[3][0] 的值
**(a + 3) a[3][0] 的值
语句/表达式 含义
*(a + 3) + 2 a[3][2] 地址
a[3] + 2 a[3][2] 地址
&a[3][2] 取得 a[3][2] 地址
a[3][2] a[3][2] 的值
*(a[3] + 2) a[3][2] 的值
*(*(a + 3) + 2) a[3][2] 的值

提示:*表示解引用一次,得到的只是地址;**表示解引用两次,得到的是值。

作函数形参

语句/表达式 含义
void fun (int a, int b[][]) 错误写法,二级指针不等同于二维数组
void fun (int a, int **b) 错误写法,二级指针不等同于二维数组
void fun (int a, int b[4][10]) 形参 b 显式给出数组的行列大小,必须将形如[4][10]的整型数组作为实参
void fun (int a, int b[][10]) 形参 b 必须至少显式给出数组的列大小,形如[x][10]的整型数组可以作为实参
void fun (int a, int (*b)[10]) 形参 b 必须至少显式给出数组的列大小,形如[x][10]的整型数组可以作为实参
void fun (int a, int *b) 可以将二维数组 T 作为 b 的实参,但在函数内部只能使用一维数组的方式去访问 T

4. 函数指针

定义声明

声明 类型 含义
int f() int () 返回值为整型的函数
int *f() int *() 指针函数)返回值为整型指针的函数
int (*f)() int (*)() 函数指针)指向函数的指针,该函数的返回值为整型
int *(*f)() int *(*)() 指向函数的指针,该函数的返回值为整型指针
int (*f[10])() int (*[10])() 数组指针)有 10 个函数指针的数组,这些函数的返回值均为整型
int *(*f[10])() int *(*[10])() 数组指针)有 10 个函数指针的数组,这些函数的返回值均为整型指针
int *(*(*f[10]))() int *(*(*[10]))() 指向一个有 10 个函数指针的数组的指针,这些函数的返回值均为整型指针
int (*f)(int, int) int (*)(int, int) 指向函数的指针,该函数有两个整型参数,其返回值为整型
int (*f)(int*, int*) int (*)(int*, int*) 指向函数的指针,该函数有两个整型指针参数,其返回值为整型
int *(*f)(int*, int*) int *(*)(int*, int*) 指向函数的指针,该函数有两个整型指针参数,其返回值为整型指针

提示:如何记忆指针函数和函数指针的区别?

  • X 型函数(函数返回的是 X 类型的数据):整型函数、浮点型函数、字符型函数组、指针函数
  • X 型指针(指针指向 X 类型的数据):整型指针、浮点型指针、字符型指针、数组指针、函数指针

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

(已定义函数int f(int a, int *b),函数指针int (*p1)(int, int*),函数指针void (*p2)(int, int*),变量int x, y

语句/表达式 含义
f 函数 f 的地址
&f 函数 f 的地址
*f 函数 f 的地址
p1 = f; f 的地址赋值给 p1
p1 = &f; f 的地址赋值给 p1
p1 = *f; f 的地址赋值给 p1
(*p1)(x, &y); 执行 p1 指向的函数 f
(void (*)(int, int*))f 对函数 f 进行类型强制转换(int -> void)
p2 = (void (*)(int, int*))f; f 的地址赋值给 p2
p2 = (void (*)(int, int*))&f; f 的地址赋值给 p2
p2 = (void (*)(int, int*))*f; f 的地址赋值给 p2
(*p2)(x, &y); 执行 p2 指向的函数 f

注:关于不同参数列表的函数指针类型强制转换,请参考关于函数指针类型强制转换的一些摸索

作函数形参(回调函数)

语句/表达式 含义
int fun (int a, int b, int (*callback)(int, int*)) 最后一个参数是函数指针,它的返回值为 int,有两个参数
typedef int (*callback)(int, int*); 定义一个函数指针
int fun (int a, int b, callback p) 最后一个参数是函数指针
posted @ 2023-03-14 15:56  漫舞八月(Mount256)  阅读(76)  评论(0编辑  收藏  举报