【C++】一篇文章,让你不再害怕指针

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zll_0405/article/details/83245745

在C++中,比较难以理解的就是指针,最常用的也是指针.这篇文章,结合我的所学,所看,来谈谈C++中的指针

指针是什么

指针是一个特殊的变量,指向内存中的一个地址.它具有四个要素:
指针类型:即指针本身所具有的类型.比如:int * p,表示指针的类型是int *
指针所指向的类型:int * p表示指针所指向的类型是int类型
指针的值:指针的值被编译器当作一个地址,而不是一个一般的数值.而指针所指向的内存区就是从指针的值所代表的的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区.比如说一个指针的值是XX,就是说该指针指向了以XX为首地址的一片内存区域.
指针本身所占据的内存区:这个内存区大小,只需要使用sizeof(指针的类型)来测一下就知道了

指针的算术运算

指针可以加上或者减去一个整数.指针的这种运算意义和通常数值的加减运算意义是不一样的,它以单元为单位.来,咱们举个例子:

char a[20];
int *ptr=(int *)a;   //强制类型转换
ptr++;

咱们来看看在上面的程序中,它是如何进行加减的.
首先定义了数组a的类型为char类型,大小为20.
然后定义了指针ptr,类型为int *,它指向的类型是int,被初始化为指向整型变量a.
最后,ptr++表示指针ptr被加了1,但是对于编译器来说,它是把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4,因为在32位程序中,int占4个字节.由于地址是用字节做单位的,所以ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节.由于char类型的长度是一个字节,所以原来ptr是指向数组a的第0号单元开始的4个字节,此时指向了数组a中从第4号单元开始的4个字节.
指针加减乘除一个整数时,都是如此,都是以单元为单位来进行的.
但是指针不能加指针,这是非法操作,因为进行加法之后,得到的结果是一个不知所向的地方,而且毫无意义.指针可以减指针,但类型必须相同,一般用在数组操作方面.

运算符&和*

在指针运算符中,最常见的就是&和*这两个了.
&是取地址符,是间接运算符
&a的运算结果是一个指针,指针的类型就是a的类型加一个
,指针所指向的类型是a的类型,指针所指向的地址就是a的地址
*p的运算结果就是看p所指向的内容.比如 * p=12, * p的类型是int,所占用的地址就是p所指向的地址,即12

指针表达式

一个表达式的结果如果是一个指针,那么这个表达式就叫指针表达式,比如:

int a;
int *pa;
pa=&a;   //这就是一个指针表达式

由于指针表达式的结果是一个指针,所以指针表达式也具有指针具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存

数组和指针的关系

数组的数组名其实可以看作一个指针.
字符串相当于是一个数组,在内存中以数组形式储存,只不过字符串是一个数组常量,内容不可改变,且只能是右值.如果看成指针的话,它既是常量指针,也是指针常量.

  • 假设,我们声明了一个数组TYPE array[n],那么这个数组名称array就有了两重含义:
    • 它代表整个数组,类型是TYPE[n]
    • 它是一个常量指针,该指针类型是TYPE*,该指针指向的类型是TYPE.该指针的值是不能修改的
  • 在不同的表达式中,数组名array可以扮演不同的角色
    • 在表达式sizeof(array)中,数组名array代表数组本身,这时sizeof函数测出的是整个数组的大小
    • 表达式array+n中,array扮演的是指针,所以sizeof(array+n)测出的是指针类型的大小.
  • 指针和结构类型的关系

    可以声明一个指向结构类型对象的指针.
    所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙.但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或者别的什么对齐方式,也就是说需要在相邻两个成员之间加若干个"填充字节".这就导致各个成员之间会有若干个字节的空隙.
    基于此,假设指针*p访问到了结构对象的第一个成员,但是不能保证 *(p+1)就一定能访问到第二个成员.因为成员之间有可能会有若干个填充字节.所以我们要使用指针指向对象时,一般使用ptr->对象名

    指针和函数的关系

    可以把一个指针声明为一个指向函数的指针,可以作为函数的形参,也可以作为实参.

    指针类型转换

    当初始化一个指针或者给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式.
    来举个例子:

    float f=12.3;
    float *ptr=&f;
    int *p;
    

    这时,如果我们想让指针p指向实数f,应该怎么办呢?p=&f?
    不对.因为指针p的类型是int *,指向的类型是int,而&f的结果是一个指针,它的类型是float *,指向的类型是float.两者类型不一致,直接赋值是肯定行不通的.
    此时,我们就需要用到"强制类型转换":p=(int *)&f;

    总结一下就是:
    如果有一个指针,我们需要把它的类型和所指向的类型改为TYPE *TYPE
    语法格式为:(TYPE *) p;
    

    关于指针的内容,逃不过这些了.
    愿你有所收获,感谢您的阅读~

    猜你喜欢

    转载自blog.csdn.net/zll_0405/article/details/83245745