【C++】初次学习C++指针时的一些易混或疑惑的地方
C++中的指针是一个比较复杂的知识概念,最近我有在学习这一方面的知识,就借此文章记录一下在学习时容易产生的混淆。本人初次发技术类的分享,可能会有纰漏,欢迎诸位指正^_^!
1、*在两种语境下的含义
先看这么一段代码:
1 int i = 330;
3 int *p = &i;
5 cout << *p <<endl;
我们都知道,*是反向取址运算符(即依址取值)。
cout <<*p <<endl; 是依 p变量上的值 为址取值,那么输出330 是符合“*是反向取址运算符”这句话的叙述的。
但是对于 int *p = &i;这句呢?
不是说*是反向取址运算符么? 那不就应该是p依址取值的那块内存写入i的地址么?但这不符合逻辑啊?
其实,在*在声明语句中并不是反向取址运算符,要把int和*看做一个整体,即int* p这样的写法更合适,我在上面个的代码中故意写成int *p就是为了举这个例子。(注意:int *p 和 int* p都是合法的)C++的基本数据类型有一个指针类型,int*则是p变量的类型声明,虽然语法上支持int *p这样int和*空开的写法,但两者应该作为一个整体理解。
小结一下:在指针变量(常量)之前的*是反向取址运算符。在声明类型时,*是指针类型声明的一部分。
2、关于数组名
传统艺能,先看代码:
1 int array[] = {1,2,3,4,5};
2
3 int* p = array;
如果我问你数组名的本质是什么?你会不会回答我是指针常量?而且还用上面的第二行代码向我作证,说:”你看,array都可以向指针p赋值,难道不是指针么?”
如果你是这么想的话,请看下面的代码:
1 cout << sizeof(p) << endl; // 输出4
2
3 cout << sizeof(array) <<endl; // 输出6(即数组大小)
惊不惊喜?意不意外?
其实解释是这样的:
(1)array的本质是数组这个数据结构,即解释了为什么cout <<sizeof(array); 的输出是数组所占内存6byte,而不是指针的大小4byte。
(2)array可以被强制类型转化为指针类型,此时array 等价于 &array[0] ,即数组首元素的地址,并以指针常量的形式表现。
3、chAR* 与 CHAR[] 的区别
为了方便待会儿引述,先举一个例子:
1 char* p = “abc” ;
2
3 char a[] = “abc”;
p是常量的指针,即存储常量地址的变量。你可以修改p的指向,如p = &XXX 是合法的。但是,你不可以修改*p指向的值,如*p++;是非法的,因为它指向的是一个常量。
a则是表现为指针常量,即a指向的地址不可以被修改的,如a++;是非法的。【特别注意:*(a++)并没有修改a的值,这是合法的,因为这里的a++是传值不是传引用】但是对于地址上的值的修改则是合法的,如*a = ‘d’;
4、综合应用
结合上面学到的三点,不妨试着解释一下*pa输出的是什么。
1 char* pArray[] ={"apple","pear","banana" };
2
3 char** pa = pArray;
4
5 cout<< *pa <<endl; //注意,cout会对char数组的指针做运算重载,输出整个数组
解:
首先 char* pArray的元素应该是一个char型指针,而“apple“是一个char数组啊?怎么能赋值呢?注意我在数组名中提到的,数组这个数据结构可以被强制类型转换为指针类型,此时”apple“等价于 &’a’(伪代码,指”apple“中第一个字符‘a’的地址)。
其次,因为pArray此时等价于&pArray[0],而pArray[0]又是一个char指针,所以,pa的类型声明就应该是指针的指针。
最后,*pa实际就等价于pArray[0]亦等价于&’a’(伪代码,指”apple”中第一个字符‘a’的地址),但由于cout重载机制,输出整个数组,即为”apple”。
【C++】初次学习C++指针时的一些易混或疑惑的地方的更多相关文章
- (转) 学习C++ -> 指针初步
学习C++ -> 指针初步 一.指针 1. 什么是指针? 我们知道, 计算机的内存是由一个个独立的存储单元组成, 并且系统会对每一个存储单元分配一个唯一的号码, 称为这个存储 ...
- C/C++学习笔记----指针的理解
指针是C/C++编程中的重要概念之一,也是最容易产生困惑并导致程序出错的问题之一.利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯:指针能 ...
- 学习K&R时初学者经常遇到的一个问题——EOF
学习K&R时初学者经常遇到的一个问题——EOF
- C++学习之指针的常见错误
C++学习之指针的常见错误 我们在编程的过程中,有时候在使用指针的时候,删除一个指针以后一定要将这个指针设置为空指针,这是因为删除这个指针只是删除这个指针指向的地址,这个指针还真是的存在程 ...
- c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放
看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...
- MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转
MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等. ...
- 初次学习asp.net core的心得
初次学习Asp.Net Core方面的东西,虽然研究的还不是很深,今天主要是学习了一下Asp.Net Core WebAPI项目的使用,发现与Asp.Net WebAPI项目还是有很多不同.不同点包含 ...
- 第一次作业:学习C++指针
1 内存空间的访问方式 计算机的内存存储器被划分为一个个存储单元.储存单元按一定的规则编号,这个编号就是存储单元的地址.地址编码的基本单位是字节,每个字节由8个二进制位组成,也就是说每个字节是一个基本 ...
- matlab学习笔记7-定时器
一起来学matlab-matlab学习笔记7-定时器 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...
随机推荐
- 【秒懂Java】【第1章_初识Java】02_软件开发
通过上一篇文章<01_编程语言>,我们了解到 Java是众多编程语言中的其中一种 编程语言可以用来开发软件 因此,我们即将要学习的Java技术,是属于软件开发的范畴.那软件开发的前景如何呢 ...
- python根据列表创建文件夹,拷贝指定文件
内容涉及:关键字定位,列表去重复,路径组装,文件夹创建,文件拷贝,字符串分割 list.txt的内容为包含关键字的文件路径,如:关键字 ’181‘ org/20190523/1/20190523201 ...
- 错误C2280 Union:尝试引用已删除的函数
在编写Union共用体类型的时候,写了如下代码,在第5行出现错误: #include <iostream> #include <string> using namespace ...
- 进度条的使用 Progress控件
MFC编程实例二:进度条的使用 2011-03-22 09:09:09| 分类: C++(C语言) | 标签:进度 nlower nupper 添加 mfc |字号 订阅 本人用的 ...
- Spring Boot是什么?
背景 最近因公司需要,开始研究java相关的开发,之前一直从事.net相关开发,所以写的或者理解的不对的地方呢,希望大家批评指正. 首先开发框架吧,就像.net很早之前有asp.net webForm ...
- web前端达到什么水平,才能找到工作?
前端都需要学什么(可以分为八个阶段)<1>第一阶段: HTML+CSS:HTML进阶. CSS进阶.DIV+CSS布局.HTML+CSS整站开发. JavaScript基础:Js基础教程. ...
- spark | 手把手教你用spark进行数据预处理
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark专题的第七篇文章,我们一起看看spark的数据分析和处理. 过滤去重 在机器学习和数据分析当中,对于数据的了解和熟悉都是最基 ...
- 基于C#实现DXF文件读取显示
工控领域的制图软件仍然以AutoCAD为主,很多时候我们希望上位机软件可以读取CAD的图纸文件,从而控制设备按照绘制的路线进行运行,今天给大家分享的是如何使用C#读取DXF文件并进行显示. 公众号:[ ...
- Appium移动端自动化测试--搭建模拟器和真机测试环境
详细介绍安装Android Studio及Android SDK.安装Appium Server. 文章目录如下 目录 文章目录如下 模拟器--安装Android Studio及Android SDK ...
- 常见的H5移动端Web页面Bug问题解决方案总汇
解决jquery ajax调用远程接口的跨域问题 首先,接口必须允许远程调用.这是后端或者运维的事情.你必须保证你得到的一个接口是允许远程调用的.否则,就没啥了. $.ajax({ type:'get ...