
【C/C++】指针详解
前言
本文花费了大约一个星期的时间来准备,然后又花了将近一个星期的课余时间来编写,课太多了,有时候一整天都没多少时间写文章,这篇文章前后花的时间不同,对指针理解程度也是在逐步加深的情况下慢慢写出来的,所以你会发现这篇文章前后的风格有很多不同。这篇文章也是在查阅了很多资料后才写出的总结,对新手来说也是很友好的,但是还是建议要有一定的C/C++语言基础再来阅读。
特别是要注意文章中使用的语言,C语言和C++还是有区别的,本文是更偏向于使用C++语言的,因为大二课程都是用的C++,C用的很少。
本文使用的编译器为:
CLion 2025.2.2 内部版本号 #CL-252.26199.153,2025年9月18日 构建 (Windows系统)
运行时版本: 21.0.8+1-b1038.71 amd64 (JCEF 122.1.9) VM: OpenJDK 64-Bit Server VM,JetBrains s.r.o. .NET Core v8.0.11 x64 (Server GC)
CLion 2025.2.2 Build #CL-252.26199.153, built on September 18, 2025 (mac系统)
Source revision: 81b8711b6961c
For non-commercial use only.
Runtime version: 21.0.8+9-b1038.71 aarch64 (JCEF 122.1.9)
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Toolkit: sun.lwawt.macosx.LWCToolkit
macOS 15.7
.NET Core v8.0.11 ARM64 (Server GC)
GC: G1 Young Generation, G1 Concurrent GC, G1 Old Generation
本文在中的代码,在两种系统上都有运行,分别为windows和mac这两种系统,但是大多时间都是在windows上进行测试,进入文章编写最后关头才使用的mac系统测试,因为文章编写花费了太多的时间,所以后续也就没有对文章前面进行修改了,可怜可怜我吧,我快被这指针干掉了 所以让我偷偷懒吧 ,不过大家也应该能看懂,而且很多人用的系统也大多都是Windows。
指针变量
常见的基本数据类型
C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了七种基本的 C++ 数据类型:
| 类型 | 关键字 |
|---|---|
| 布尔型 | bool |
| 字符型 | char |
| 整型 | int |
| 浮点型 | float |
| 双浮点型 | double |
| 无类型 | void |
| 宽字符型 | wchar_t |
有很多人可能没听说过wchar_t (我也没有听说过)
1 | typedef short int wchar_t; //占用2字节 |
所以 wchar_t 就相当于C语言里面的 short int
空指针
在学习指针时容易出现很多问题,就包括了指针赋值的事情,空指针是一个很好的解决办法。
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。NULL 指针是一个定义在标准库中的值为零的常量。
在C++11 新增了类型nullptr,关键字nullptr表示空指针字面量。它是一个类型为 std::nullptr_t 的 纯右值。存在从 nullptr到任何指针类型和任何成员指针类型的空指针值的隐式转换。对于任何空指针常量也存在类似的转换,其中包括类型为 std::nullptr_t 的值以及宏 NULL。
加入nullptr的原因:c++中nullptr_c++ nullptr-CSDN博客这篇文章有解释,我就不做过多解释了。
| nullptr(c++ 11新增) | 空指针常量 | int* ptr = nullptr; |
|---|---|---|
| null | 通常被定义为整数 0 | #define NULL ((void *)0) |
整型(int)
int p – 这是一个普通整形变量,占用字节数为 4 bytes,保存的是整数
int p[5] – 这是一个普通整形数组变量,占用字节数为 5×4=20 bytes,可以保存5个整数
int p – 这是一个整型指针变量,p是指向整型的指针变量,占用字节数为 64 bit/8 = 8 bytes(64位系统),指针变量p保存的是*地址,表示p所指向的地址里面存放的是一个int类型的值。
int *p[5] – 这是一个整型指针数组变量,p是指向整型指针的数组,占用字节数为5×8=40 bytes(64位系统),数组p保存的也是地址,它保存了5个指针变量为元素,其中每一个元素都是地址,所指向的地址里面存放的是一个int类型的值。(数组名p是数组首元素的地址,等于&p[0]和&p ,但是&p是指向整个数组指针的指针 int * ( * )[5],&p[0] 的类型是指向指针的指针 int ** ,他们的地址值是相同的,但是类型不同)
int (p)[5] – 这也是一个整型*指针变量,p是一个指向整型数组的指针变量,占用字节数为8 bytes(64位系统),数组指针p保存的还是地址,但是p是一个指向包含5个整型的数组的指针变量,p保存的是整个数组的地址,而不是数组的首地址,虽然数值上,整个数组的地址和首元素地址是相同的,p++相当于位移了整个数组的字节大小。
看下面的代码,更好理解:
1 | int a = 6; |
输出结果:
1 | 6 6 7 |
字符型(char)
char a; – 这是一个普通字符型变量,占用字节数为1 byte,用于存储单个字符。
char a[5]; – 这是一个字符数组,占用字节数为5×1= 5 bytes,用于存储字符串。
char *a; – 这是一个字符指针变量,占用字节数为8 bytes(64位系统),指针a保存的是地址,用于指向字符串或者动态内存分配。
char *a[5]; – 这是一个字符指针数组,占用字节数为5 × 8 = 40 bytes(64位系统),指针数组a保存的是地址,用于储存字符串数组。
string s; – 这是C++的string类,与C语言的string截然不同,详细见C++ string标准库 | 菜鸟教程,这句的作用是声明字符串变量s,占用字节数为32 bytes,用于存储字符串。
看下面的代码,更好理解:
1 | string s = "Hello!World"; //使用的是C++标准库中的string类 |
输出结果(下面的仅供参考,下面的结果是在mac系统上运行出来的,与Windows系统上还是有很多不同的):
1 | Hello!World Hello!World |
疑问解答
cout << &a 为什么乱码?
cout<<(void*)&a 为什么是正确的?
这是因为cout 对 char* 有特殊处理:
cout 的设计逻辑:
- 当遇到 char* 类型时,cout 认为这是一个C风格字符串的起始地址
- 它会从该地址开始,连续输出字符,直到遇到 null 终止符 (\0)
- 由于 &a 只是单个字符的地址,后面没有 \0,所以会继续输出后面的内存内容,这就导致了乱码。
解决办法:C 风格的强制转换类型为 void * 或者使用 C++强制类型转换运算符 static_cast <void *>,这两种效果都是一样的。
总结
注意事项
1.C/C++ 不允许将完整类型的指针赋值给不完整类型的指针
2.给变量赋值前,要弄清值的类型,防止类型不同而导致报错
3.数组在表达式中会自动退化为指针
4.cout遇到char* 类型时,会连续输出字符,直到遇到\0
参考引用:





