C++的指针相关概念
引言
初入c++,肯定会对指针这个概念非常熟悉。但是为什么c/c++要使用指针?
其实每一种编程语言都使用指针,指针并不只是C/C++的独有特性。C++将指针暴露给了用户(程序员),而Java和C#等语言则将指针隐藏起来了。不光如此,指针还有很多妙用,后面会着重展开详解。
一。指针(*)的概念分析
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
- 指针的类型 *指针变量的名称;
eg: int *p
要搞清一个指针需要搞清指针的四方面的内容:
- 指针的类型
- 指针所指向的类型
- 指针的值或者叫指针所指向的内存区
- 指针本身所占据的内区。
相关链接:一文让你不再害怕指针之C指针详解(经典,非常详细) - 知乎 (zhihu.com)
指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。必须加以区分!!!
首先,先来看几个复杂类型的指针声明(有难入易更容易理解)
- int p; //这是一个普通的整型变量
- int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针
- int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组
- int *p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组
- int (*p)[3]; //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针
- int **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.
- int p(int); //从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的int 结合,说明函数的返回值是一个整型数据
- Int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针
二。指针的算术运算
指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、--、+、-。
假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:
- ptr++
在执行完上述的运算之后,ptr 将指向位置 1004。如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。
因为int类型在32位程序中占4个字节,字符char类型占1个字节
递增一个指针
我们喜欢在程序中使用指针代替数组,因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。下面的程序递增变量指针,以便顺序访问数组中的每一个元素:
- int array[20]={0};
- int *ptr=array; // 指针中的数组地址
- for(i=0;i<20;i++)
- {
- (*ptr)++;
- ptr++;// 移动到下一个位置
- }
这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1 个单元(prt++),所以每次循环都能访问数组的下一个单元。
三。运算符&和*
C++ 提供了两种指针运算符
- 取地址运算符 & :& 是一元运算符,返回操作数的内存地址。例如,如果 var 是一个整型变量,则 &var 是它的地址。&var 的运算结果是一个指针
- 间接寻址运算符 * :间接寻址运算符 *,它是 & 运算符的补充。* 是一元运算符,返回操作数所指定地址的变量的值。
- int main ()
- {
- int var = 3000;
- int *ptr;
- int val;
- // 获取 var 的地址
ptr = &var; //输出prt=0xbff64494(即3000的地址)
- // 获取 ptr 的值
val = *ptr; //输出val=3000
- }
四。数组和指针的关系
数组的数组名其实可以看作一个指针。看下例:
- int array[10]={0,1,2,3,4,5,6,7,8,9},value;
- ...
- ...
- value=array[0];//也可写成:value=*array;
- value=array[3];//也可写成:value=*(array+3);
- value=array[4];//也可写成:value=*(array+4);
上例中,一般而言数组名array代表数组本身,类型是int [10],但如果把array看做指针的话,它指向数组的第0个单元,类型是int *,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。其它依此类推。
五。指针和结构类型的关系
可以声明一个指向结构类型对象的指针。
- struct MyStruct
- {
- int a;
- int b;
- int c;
- }
- MyStruct ss={20,30,40};//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。
- MyStruct *ptr=&ss;//声明了一个指向结构对象ss的指针。它的类型是MyStruct*,它指向的类型是MyStruct。
怎样通过指针ptr来访问ss的三个成员变量?
- ptr->a;
- ptr->b;
- ptr->c;
C++的指针相关概念的更多相关文章
- C09 指针
目录 指针相关概念 指针变量 null指针 指针的算术运算 指针数组 指向指针的指针 传递指针给函数 从函数返回指针 指针相关概念 变量 如果在程序中定义了一个变量,在对程序进行编译时,系统就会为这个 ...
- 快速上手系列-C语言之指针篇(一)
快速上手系列-C语言之指针篇(一) 浊酒敬风尘 发布时间:18-06-2108:29 指针的灵活运用使得c语言更加强大,指针是C语言中十分重要的部分,可以说指针是C语言的灵魂.当然指针不是万能的,但没 ...
- C++面试题汇集
1.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?答:首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可以 ...
- c++面试常见160问
1.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern "C"?答:首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其 ...
- 再次探讨C++的动态绑定和静态绑定
以前在学习C++的时候,对动态绑定和静态绑定的理解是:静态绑定是编译时决定的,非虚函数基本都是静态绑定:而动态绑定用于虚函数,是为了实现多态.这样理解没什么大的问题,但我一直疑惑的是,既然静态绑定可以 ...
- 20160212.CCPP体系详解(0022天)
程序片段(01):01.二维数组.c 内容概要:二维数组 #include <stdio.h> #include <stdlib.h> //01.关于栈内存开辟数组: // 诀 ...
- C++面试常见问题
转载:https://zhuanlan.zhihu.com/p/34016871?utm_source=qq&utm_medium=social 1.在C++ 程序中调用被C 编译器编译后的函 ...
- 面试中的C++常见问题
1.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”? 答:首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可 ...
- C语言学习书籍推荐《学通C语言的24堂课》下载
下载地址:点我 编辑推荐 <学通C语言的24堂课>:用持续激励培养良好习惯以良好习惯铸就伟大梦想——致亲爱的读者朋友在开始学习<学通C语言的24堂课>的同时,强烈建议读者朋友同 ...
随机推荐
- java中常见的内存泄露的例子
JAVA 中的内存泄露 Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露. Java中的内存泄露与C++中的表现有所不同. 在C++ ...
- electron踩坑系列之一
前言 以electron作为基础框架,已经开发两个项目了.第一个项目,我主要负责用react写页面,第二项目既负责electron部分+UI部分. 做项目,就是踩坑, 一路做项目,一路踩坑,坑多不可怕 ...
- Apache SkyWalking 告警配置指南
Apache SkyWalking Apache SkyWalking是分布式系统的应用程序性能监视工具(Application Performance Management,APM),专为微服务.云 ...
- BUAA_2020_OO_UNIT1_REVIEW
OO第一单元总结 一.程序结构分析 总的来说,这一学期我才开始正式的接触面向对象的思想,直到pre才开始正式的实践,所以这次作业可能写的有一些混乱,第三次作业也进行了大量重构. 1. 第一次作业 关于 ...
- (二)Struts2配置文件
一.web.xml文件 web.xml配置文件是一种J2EE配置文件,决定servlet容器的HTTP元素需求如何进行处理.它严格来说不是一个Struts2 配置文件,但它是Struts2 运作所需要 ...
- 敏捷史话(十四):敏捷之峰的攀登者 —— Jim Highsmith
"我们希望,一起组成的敏捷联盟能够帮助到其他同行,帮他们用新的更'敏捷'的方式去思考软件开发.方法论和组织.做到这一点,我们就得偿所愿了."Jim Highsmith 在雪鸟会议结 ...
- hahahah JavaScript 小小小细节
nice~!
- 又一起.NET程序挂死, 用 Windbg 抽丝剥茧式的真实案例分析
一:背景 1. 讲故事 前天有位粉丝朋友在后台留言让我帮忙看看他的 Winform程序 UI无响应 + 410线程 到底是啥情况,如下图: 说实话,能看到这些真实案例我是特别喜欢的 ,就像医生看病,光 ...
- java面试系列<2>——java容器
1.概览 容器主要包括Collection和Map两种,Collection存储着对象的集合,而map存储着键值对(两个对象)的映射表 Collection 1.set TreeSet:基于红黑树实现 ...
- DevEco Device Tool 2.1 Beta1 的Hi3861在Windows平台的编译体验
DevEco Device Tool迎来了2.1 Beta1,其中的亮点之一是:支持Hi3861开发板的源码在Windows平台编译.带着浓厚的兴趣,第一时间做了一次体验. 首先在官网下载" ...