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

Posted Mount256

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++的指针用法总结相关的知识,希望对你有一定的参考价值。

文章目录

1. 普通指针

定义声明

声明类型含义
int aint整型变量
int *aint *一级指针)指向整型变量的指针
int **aint *(*)二级指针)指向一个指向整型变量指针的指针
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 字节)
++pp 地址自增一个 int 长度(4 字节)
*p++先获取 p 所指向的内容,p 地址再自增一个 int 长度(4 字节)(*和++同优先级,结合方向为从右往左
*(p++)先获取 p 所指向的内容,p 地址再自增一个 int 长度(4 字节)
++*pp 地址先自增一个 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

语句/表达式含义
aa[0] 地址
&a取得 a[0] 地址
&a[0]取得 a[0] 地址
&a[5]取得 a[5] 地址
a + 5a[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 - p2p1 和 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,11int [][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;

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

语句/表达式含义
aa[0][0] 地址,或 0 行起始地址
*aa[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] 的值
**aa[0][0] 的值
语句/表达式含义
a + 3a[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) + 2a[3][2] 地址
a[3] + 2a[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)最后一个参数是函数指针

以上是关于C/C++的指针用法总结的主要内容,如果未能解决你的问题,请参考以下文章

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

c/c++中const用法总结

C语言【函数 数组 指针】利用指针求一维数组的数据元素之和

C语言指针基本概念及其指针变量的定义是啥

c++c++面试知识6——第六章 语言特性相关

还不懂 C/C++ 指针结构体指针指针函数函数指针?赶紧看过来!