关于指针的一些基本常识
这两天因为工作需要,很是纠缠于C++中的指针(严格意义上来说应该算是C),虽然已经不算是初学者了,但是因为很长时间没有使用,还是有很多混淆的地方,所以干脆在此做一个总结。
首先定义一个最简单的int指针:
1 #include <iostream> 2 using namespace std; 3 4 int main(void) 5 { 6 int *single_pointer; 7 cout<<single_pointer; 8 cout<<*single_pointer; 9 }
可以看到VS2005的输出如下:
究其原因,因为只给出了指针的声明,却没有初始化,因此当执行到cout输出时,会出现访问内存错误的情况。
修改代码:
1 #include <iostream> 2 using namespace std; 3 4 int main(void) 5 { 6 char ch = 'a'; 7 char *pointer_1 = &ch; 8 printf("%c\n", ch); 9 printf("%p\n",&ch); 10 printf("%p\n", pointer_1); 11 printf("%p\n",&pointer_1); 12 printf("%c\n",*pointer_1); 13 }
输出结果为:
到这里可以很明显的看出:
0x0018FF2B为字符ch的地址,
指针pointer_1指向字符ch的内存地址,所以pointer_1与对字符ch取地址&ch的打印结果是一样的。
而0x0018FF1C则为指针pointer_1本身的值。
或许这样可以看得更清楚:
只要搞清楚,指针本身也是一种数据类型,占用空间大小为四个字节,就很容易理解这一点了。
接着是二维指针,亦即所谓的指针的指针。
话不多,先贴代码:
1 #include <iostream> 2 using namespace std; 3 4 int main(void) 5 { 6 char **pPointer = NULL; 7 pPointer = (char **)malloc(10 * sizeof(char *)); 8 9 *pPointer = "12"; 10 *(pPointer + 1) = "345"; 11 *(pPointer + 2) = "6789"; 12 13 printf("*pPointer: %s\n\n",*pPointer); 14 15 printf("P *pPointer: %p\n",*pPointer); 16 printf("P *(pPointer + 1): %p\n",*(pPointer + 1)); 17 printf("P *(pPointer + 2): %p\n\n",*(pPointer + 2)); 18 19 printf("& &*pPointer: %p\n",&(*pPointer)); 20 printf("& &*(pPointer + 1): %p\n",&*(pPointer + 1)); 21 printf("& &*(pPointer + 2): %p\n\n",&*(pPointer + 2)); 22 23 printf("P pPointer: %p\n",pPointer); 24 printf("P pPointer + 1: %p\n",pPointer + 1); 25 printf("P pPointer + 2: %p\n\n",pPointer + 2); 26 27 printf("& pPointer: %p\n",&pPointer); 28 printf("& pPointer + 1: %p\n",&pPointer + 1); 29 printf("& pPointer + 2: %p\n\n",&pPointer + 2); 30 31 printf("C **pPointer: %c\n",**pPointer); 32 printf("C **pPointer + 1: %c\n",**pPointer + 1); 33 printf("C **pPointer + 2: %c\n\n",**pPointer + 2); 34 35 printf("S *pPointer: %s\n",*pPointer); 36 printf("S *pPointer + 1: %s\n",*pPointer + 1); 37 printf("S *pPointer + 2: %s\n\n",*pPointer + 2); 38 39 printf("S *pPointer: %s\n",*pPointer); 40 printf("S *(pPointer + 1): %s\n",*(pPointer + 1)); 41 printf("S *(pPointer + 2): %s\n\n",*(pPointer + 2)); 42 43 printf("& &pPointer: %p\n",&pPointer); 44 printf("& &(*pPointer): %p\n\n",&(*pPointer)); 45 46 printf("D sizeof(*pPointer): %d\n",sizeof(*pPointer)); 47 printf("D strlen(*pPointer): %d\n",strlen(*pPointer)); 48 printf("D sizeof(**pPpointer): %d\n\n",sizeof(**pPointer)); 49 }
VS2005下的输出为:
首先明确一点?何为指针?
看一个最简单的指针的定义:char *p
首先,指针本身是一种数据格式,有别于int这样的基本数据类型,它会指向一块指定的内存(所以指针如果没有初始化会出现野指针的情况)。因此,作为指针数据类型,p本身会在内存中占用一块大小为sizeof(void *)在本文中值则为4的内存,同时因为p被声明为char *而不是void *,所以p所指向的内存中存放的是一个char类型的值,占一个字节。
理解这一段之后再来看所谓二维指针的定义,也就很容易理解了。
来看二维指针的定义:char **p,实际上应该理解为(char *) *p
亦即,p为一个指针,p所指向的内存中存放的数据为另一个指针,而这个p指针所指向的指针指向的最终内存块存放的为一个char值,p->another_pointer->char。
笔者做了一个粗略的描述图:
其中temp_1-3三个指针为笔者虚拟的存在,分别代表指针pPointer,pPointer+1与pPointer+2所指向的内存。
此时再来看上面的输出:
pPointer为指向指针的指针,它在内存中的地址为0X0018FF28,它所指向的内存为&*pPointer,也就是上图中temp_1的位置,为0X00520F60,可以看到由于申请内存的大小为10*sizeof(char *),因此temp_1-3的三块地址是连续在一起的。
而*pPointer本身也是一个指针,它所指向的内存地址为0X00415984,该内存中存放的是一个char型的字符,值为‘1’
最后,对代码中的一些输出做一些解释:
名称 | 类型 | 解释 |
pPointer | 指针 | 指针的指针 |
*pPointer | 指针 | pPointer所指向的内存中存放的指针 |
**pPointer | 字符 | 对指针(*pPointer)做解引用操作所获取的值 |
&*pPointer | 地址 | pPointer所指向的内存地址,亦即上文中temp_1指针的地址(区别于指针指向的地址) |
pPointer+1 | 指针 | 指针pPointer所指向的内存的后一块内存,亦即上文中的temp_2 |
*pPointer+1 | 指针 | 指针*pPointer(亦即temp_1)所指向内存的后一块内存,上文中为字符‘2’所在的内存 |
转载于:https://www.cnblogs.com/chrischeng/p/4410403.html
关于指针的一些基本常识相关推荐
- win10禁用笔记本自带键盘和触控板
禁用键盘 以管理员身份运行cmd,输入: sc config i8042prt start= disabled 如果提示执行成功,重启即可.不成功的话只能去找其他方法,例如换一个错误的驱动程序等. 如 ...
- MIT 6.s081学习笔记
MIT 6.s081学习笔记 introduction 计算机组织结构: 最底部是一些硬件资源,包括了CPU,内存,磁盘,网卡 最上层会运行各种应用程序,比如vim,shell等,这些就是正在运行的所 ...
- 图解c/c++多级指针与“多维”数组
2019独角兽企业重金招聘Python工程师标准>>> 前言 指针与数组是C/C++编程中非常重要的元素,同时也是较难以理解的.其中,多级指针与"多维"数组更是让 ...
- 指针数组,数组指针,指针函数,函数指针,二级指针详解
先看个简单的:char *p,这定义了一个指针,指针指向的数据类型是字符型,char *(p)定义了一个指针P: char *p[4], 为指针数组,由于[]的优先级高于*,所以p先和[]结合,p[ ...
- C语言 关于指针的格式化
写这篇文章时由于没有参考过什么权威资料教材,所以有些观点可能是错误的, 不过我本人都是经过大量调试后才写出来的啦.. 1. 内存由多个单位为8bit = 1byte的单元组成,每1个单元都配有1个编号 ...
- 将一个指针 free 两次之后会发生什么?
0x00 简介 在入门 c 语言时我们都知道一个常识:通过 malloc() 动态申请的内存在使用完之后需要通过 free() 释放:那么如果因为程序设计不当,导致这块堆内存释放之后,再释放一次会发生 ...
- python入门常识
Django开发心得: filter方法可以使用count(),update().get方法不可以使用. 密码重置功能和修改功能.项目链接功能.(前端模板表单向后台传输数据时,有post和get两种方 ...
- 彻底搞定C指针-——第五篇:函数参数的传递
一. 三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行--唉呀,谁扔我鸡蛋?) 1. 考题一:程序代码如下: void Exchg1(int x, int y) { in ...
- 实用常识_实用垃圾收集,第1部分–简介
实用常识 这是我打算写的一系列博客文章的第一部分,其目的是解释垃圾回收在现实世界中如何工作(尤其是在JVM中 ). 我将介绍一些我认为对于充分理解垃圾收集对于实际目的是必需的理论,但是将其降至最低. ...
- C1认证学习十三(数据结构常识)
C1认证学习十三(数据结构常识) 任务背景 数据结构是计算机中存储.组织数据的方式,他研究如何构造复杂的软件系统,它的核心是如何分解以及抽象,并且得到软件开发过程中的所需要的逻辑结构. 任务目标 1. ...
最新文章
- 【转载】Asp.Net 全生命周期
- MPB:南土所褚海燕组-​非靶标代谢组测定土壤可提取有机碳组分
- 在envi做随机森林_随机森林原理
- 计算机系统基础:校验码知识笔记
- NVIDIA TESLA M40
- jvm学习笔记(3)——java对象的内存分配和对象的回收(GC)
- mysql 远程访问
- Java实现国密算法SM2,SM3,SM4,并且实现ECB和CBC模式
- python矢量化运算_Python里面的矩阵与矢量化运算
- 每年的节假日数据处理
- unity 编辑器模式下修改屏幕分辨率
- Java读取OPC DA报错:org.jinterop.dcom.common.JIException: Access is denied. [0x80070005]
- 21个数据科学家面试必须知道的问题和答案
- 铁道部购票网站可能造成另一次的密码危机
- 解决AutoCAD软件打开CASS软件成图字体显示成问号的问题
- 软件智能:aaas系统AI众生的“世”和“界” 之21 整定问题空间和标定解决方案空间之1
- 在使用易路代理时,本地浏览器如何修改DNS 1.1.1.1?
- MongoDB安装Mac M1
- 粉丝福利|Go并发编程学习路线图
- 2021年广东省安全员C证第三批(专职安全生产管理人员)复审考试及广东省安全员C证第三批(专职安全生产管理人员)模拟考试