引言

初入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;

最新文章

  1. html5shiv.js and respond.min.js
  2. iOS远程推送原理及实现过程
  3. Android-完全退出当前应用程序的四种方法
  4. jquery幻灯片
  5. Maven 安装以及一些开发技巧
  6. Linux操作杂记
  7. 模板类之间的友元关系实现Blob和BlobPtr
  8. 构造AJAX参数, 表单元素JSON相互转换
  9. idea 集成sonarLint
  10. 【Beta】Daily Scrum Meeting——Day1
  11. css3中的布局相关样式
  12. Java异常简介、异常捕获还是上抛总结
  13. 震惊!计算机连0.3+0.6都算不对?浅谈IEEE754浮点数算数标准
  14. Linux服务与进程状态
  15. Python ImportError: No module named &#39;requests&#39;的解决方法
  16. spring cloud(学习笔记)微服务启动错误(1)
  17. MAC OSX Xcode硬盘清理
  18. spring cloud/spring boot同时支持http和https访问
  19. 使用git push命令如何忽略不想提交的文件夹或者文件
  20. Synergy软件的基本配置/使用(详细教程)

热门文章

  1. 使用quartz.net 完成一个winform版的任务提醒工具
  2. golang 实现两数组对应元素相除
  3. Python之内存泄漏和内存溢出
  4. gsoap多wsdl集成
  5. 振兴中华(蓝桥杯13年第四届省赛真题 JAVA-B组)
  6. pycharm在debug时总是报UnicodeDecodeError
  7. 【LiteOS】LiteOS消息队列-实战
  8. Python数据分析入门(十四):数据分析中常用图
  9. 【Android】修改Android Studio的SDK位置
  10. 【设计模式】- 生成器模式(Builder)