【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 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...
随机推荐
- MongoDB via Dotnet Core数据映射详解
用好数据映射,MongoDB via Dotnet Core开发变会成一件超级快乐的事. 一.前言 MongoDB这几年已经成为NoSQL的头部数据库. 由于MongoDB free schema ...
- 上位机面试必备——TCP通信灵魂二十问【下】
上篇文章跟大家介绍了TCP通信常见的前10个面试题,没看过的小伙伴可以点击下方链接进行查看: 上位机面试必备——TCP通信灵魂二十问[上] 今天就后面的10个面试题接着做下说明:欢迎关注[dotNet ...
- 暑假集训Day2 互不侵犯(状压dp)
这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...
- js事件入门(4)
4.表单事件 表单事件处理主要用来验证表单,可以处理用户在表单上所做的任何操作. 4.1.onsubmit事件 当用户点击submit按钮来提交表单时,就会触发onsubmit事件,如果事件处理程序返 ...
- java方法中开启一个线程
很多业务场景下需要你在一个方法中去开启一个线程,去跑一些处理时间较长的代码,这样调用方就不必经过长时间的等待了.好了 话不多说 先上代码: package test; public class Th ...
- 老板急坏了,公司网站的 HTTPS 过期了
端午出去玩的时候,老板打电话说公司网站的 HTTPS 过期了,访问不了(见下图),要我立马升级一下.可惜我当时没带电脑,无能为力,可把老板急坏了. 没办法,急就先急着,只能等我有电脑了才能搞.点击高级 ...
- Fetch方法封装、业务实践
说Fetch之前啊,我们不得不说一说Ajax了,以前使用最多的自然是jQuery封装的Ajax方法了,强大而且好用. 有人说了,jQuery的Ajax都已经封装得那么好了,你还整Fetch干什么,这不 ...
- tyvj 1198 矩阵连乘——区间dp
tyvj 1198 矩阵连乘 题目描述 一个n*m矩阵由n行m列共n*m个数排列而成.两个矩阵A和B可以相乘当且仅当A的列数等于B的行数.一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算 ...
- React学习路径快速进入AntDesignPro开发
好久没有写博客,有空再来记一下.最近在整些小东西,需要用到前端,最开始本着对nodejs的动不动几百兆插件的恐惧, 于是使用自己以前写的 OSS.Pjax 小框架(类似国外的Pjax,利用pushSt ...
- Docker镜像-拉取并且运行
1.docker search : 从Docker Hub查找镜像 docker search [OPTIONS] 镜像名 OPTIONS说明: --automated :只列出 automated ...