【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 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...
随机推荐
- Python 简明教程 --- 19,Python 类与对象
微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 那些能用计算机迅速解决的问题,就别用手做了. -- Tom Duff 目录 上一节 我们介绍了Pyt ...
- Dubbo想要个网关怎么办?试试整合Spring Cloud Gateway
一.背景 在微服务架构中 API网关 非常重要,网关作为全局流量入口并不单单是一个反向路由,更多的是把各个边缘服务(Web层)的各种共性需求抽取出来放在一个公共的"服务"(网关)中 ...
- Eclipse中Debug时鼠标悬停不能查看变量值解决办法
问题描述:Eclipse在Debug模式下,当鼠标移动到某个变量上面时不自动显示该变量对应的值. 解决方法:在Eclipse中点击 Window->Preferences->Java-&g ...
- SecureCRT连接阿里云ECS服务器,经常掉线的解决方案
1 使用SecureCRT远程连接后,Options > Session Options > Terminal(终端) > 勾选 “Send protocol NO-OP”
- java面试知识迷你版
java基础JUC.AQSJVM类加载过程mybatisSpringspringboot设计模式数据库redis网络问题认证授权Nginxlinux其他lombok消息队列ES缓存分库分表设计高并发系 ...
- CSS通过text-transform实现大写、小写和首字母大写转换
再日常项目中可能会用到一些特殊的样式,比如大写字母转小写.小写字母转大写.首字母大写等. 可以通过 CSS 的 text-transform 属性来实现: text-transform 转换不同的文本 ...
- 请解释ASP. NET中的web页面与隐藏类之间的关系
请解释ASP.NET中的web页面与其隐藏类之间的关系 其实页面与其隐藏类之间就是一个部分类的关系,你在页面上放一个一个的控件就是在这个类中定义一个一个的属性, 因为是同一个类的部分类的关系,所以隐藏 ...
- swiper的自适应高度问题
#swiper的自适应高度问题 众所周知,swiper组件的元素swiper-item是设置了绝对定位的,所以里面的内容是无法撑开swiper的,并且给swiper盒子设置overflow:vis ...
- List集合-02.LinkedList
2.LinkedList 2.1 UML继承关系图 2.2 底层存储节点 通过内部类Node存储,可以看出是双向的链表结构 private static class Node<E> { E ...
- 「疫期集训day12」阴雨
我们走进了泥泞的雨林----阿尔贡森林里艰难前进的士兵 今天考试一般,T1T2签到题没啥好说的,剩下三个小时全肛T3(我脑子有泡,前几天刚做了一道类似T4的难题,公式更难推),9:00->10: ...