【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 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...
随机推荐
- Codeforces Round #651 (Div. 2)
感觉自己无可救药了. A题:找到小于等于n的两个不同的数的gcd最大是多少,显然是floort(n/2).设这两数是a * gcd, b * gcd然后gcd(a,b) = 1,那么gcd要尽量大,不 ...
- Python之浅谈面向对象
目录 面向对象和面向过程 面向过程 面向对象 类与对象 定义类 在现实世界中:先有对象,再有类 在程序中,务必保证:先定义(类),后使用(产生对象) 产生对象 类 对象 产生对象 属性查找顺序 对象赋 ...
- 【Spring注解驱动开发】如何使用@Value注解为bean的属性赋值,我们一起吊打面试官!
写在前面 在之前的文章中,我们探讨了如何向Spring的IOC容器中注册bean组件,讲解了有关bean组件的生命周期的知识.今天,我们就来一起聊聊@Value注解的用法. 项目工程源码已经提交到Gi ...
- idea为本地项目创建仓库并git到云上
1.为本地项目创建一个本地仓库: 2.在码云上创建一个仓库,(初始化的时候先不要创建README.md文件) 3.本地仓库关联远程仓库:右键项目选址git>>repository>& ...
- java中执行cmd命令
一.java执行cmd命令的三种方式:http://www.jb51.net/article/80829.htm 参考:https://www.cnblogs.com/zhufu9426/p/7928 ...
- 记录下 rhel 7 安装MySQL 并重置root密码
注意官方是很不提倡用root的. 下载并安装MySQL 最新的rpm地址 https://dev.mysql.com/downloads/repo/yum/ #wget https://repo.my ...
- 本地连接虚拟机db2V10.5遇到的问题
在连接虚拟机数据库时发现自己不知道db2的端口号是多少,百度上说50000,60000的都有,所以还是决定自己试一下,并记录下这个过程 # 首先切换到db2inst1的用户 su - db2inst1 ...
- CSS三种布局模型是什么?
在网页中,元素有三种布局模型:流动模型(Flow) 默认的.浮动模型 (Float).层模型(Layer).下面我们来看一下这三种布局模型. 三种布局模型介绍: 1.流动模型(Flow) 流动(Flo ...
- 创建新用户后无法切换 su: failed to execute /bin/bash: Permission denied
创建新用户后无法切换 su: failed to execute /bin/bash: Permission denied 当使用 su username 从root切换用户时显示 su: fai ...
- 洛谷CF1292A NEKO's Maze Game,还是思维。。。
题目直接找链接 题意: 有一个2*n大的平面,有的格子不能走,有的格子可以走,最初状态所有格子都可以走,有q个操作,每个操作都把某个格子变化一下:能走变不能走,不能走变能走,输出每次操作之后能否从1, ...