指针第三部分(“ * ”与“ & ”、指针的步长)---- 2021.1.31

上一讲指针链接:

指针第二部分(指针变量的定义、初始化、使用)---- 2021.1.29

“ * ”与“ & ”

“ * ”与“ & ”这两个符号是我们在使用指针时会频繁使用到的两种符号。
首先通过“ * ”符号取指针变量所指向的那块内存的内容,进而我们对那块内存区域进行操作。
“ & ”符号是对其那块被操作的内存区域取地址,也就是获取地址编号赋值给我们定义的指针变量。

上述说的两点,大家应该都清楚。但是我想借这个概念说一下表达式的数据类型匹配问题。

举个例子,有一个表达式 int *p = &a;
众所周知,上述表达式其实可以以另一种形式表示,也是为了让大家更好的理解,如下所示。

int *p;  
int a;
p = &a;

在上一讲中,我们已经知道了p是一个变量,那么这个变量的数据类型是int *类型。那表达式右边的变量是a,这个变量的数据类型是int类型。那我此时想问,&a这个整体是什么数据类型?

接下来我先给大家引入一个概念,在使用时,对一个表达式取*,就会对表达式降一级*,如果对表达式取&,就会对表达式加一级*

那这句话怎么理解呢?
在上述例子中,由于a变量是int类型的,那么根据上面的概念,对表达式取&,则需要对表达式加一级*,所以最终&a整体的数据类型为int*类型,正好与表达式左边的p变量的数据类型相同,最终也实现了表达式两边的数据类型匹配问题。

然后再举两个例子。

第一个例子:*p = 100;
等式右边,顾名思义,是int类型的。那么左边的变量pint*类型的,由上述概念可知,对一个表达式取*,就会对表达式降一级*,所以等式左边最终的*p整体的数据类型为int类型。

第二个例子:

int *p;
int **q;
q = &p;

等式左边,变量q的数据类型为int**类型,右边变量p的数据类型为int*类型,然后由概念可知,对表达式取&,则会对表达式加一级*,所以最终&p的数据类型为int**类型,表达式两边匹配。

指针的步长

在说这个指针步长之前我想让大家了解下指针变量的大小。
举个例子,如下图所示。

在这里插入图片描述解释如下:

  1. 我们定义了三个指针变量p1,p2,p3。并且这三个指针变量的数据类型都不同,图中我也用红框标出来了。
  2. 主要是打印三个指针变量的字节大小,其中使用到了sizeof函数。
  3. 最终结果发现,三个变量的字节大小都相同。那是因为,在上一讲也提到了,指针变量主要是用来存放地址编号的,并且我们此时的编译器是32位的,所以得出一个结论,不管什么类型的指针,大小只和系统的编译器类型有关。如果是使用64位编译器,那么结果自然而然就会变成8。

那么如果我们定义了一个双指针会怎样,结果还会一样吗?如下图所示。

在这里插入图片描述结果显而易见,是一样的,因为双指针也还是指针变量,只要是指针变量就只会存放地址编号也就是地址。所以也就印证了上述的解释中的那个结论。

那我们思考一个问题,既然无论是什么类型的指针变量所能容纳的字节大小都一样,那为啥还会有这么多的数据类型呢,比如int*char*short*double*等等。

举个例子,如下图所示。

在这里插入图片描述解释如下:

  1. 由图中可知,我们定义了一个整型变量,格式是16进制的。
  2. 然后分别定义了三个指针变量p1,p2,p3。并且分别对其num整型变量进行取地址操作。
  3. 图中进行了强制转换操作。至于为什么,拿其中一个例子来讲
char* p1 = (char*)#

等式左边p1的数据类型为char*类型,那么num变量的数据类型为int类型,并且由之前可知,为了表达式的数据类型匹配,所以进行&操作时,需要对表达式升一级*,所以&num整体的数据类型为int*类型。那么众所周知,int*char*类型不匹配,所以才会对等式右边进行强制转换。将int*替换成char*类型。

  1. 打印时我们采用%x格式输出,这个符号主要是输出16进制的int类型。
  2. 最终结果大家可以看到,三个变量的输出却不一样。这是为什么呢?接下来就正式引入步长的概念。首先char类型输出结果为04,short类型输出结果为0304,int类型输出结果为01020304。大家可能会发现这和我们定义的指针变量本身的类型有关。
    char *p 取一个字节
    short *p取两个字节
    int *p取4个字节
    所以其实我们可以将这个步长理解为宽度,也就是通过*取指针变量的所指向的那块内存空间的内容时,取得内存的宽度(步长)和指针变量本身的类型有关。
    那么求取指针变量的步长的操作可以通过sizeof函数实现。例如char *p可以等价为sizeof(char)
    步长sizeof(将指针变量与指针变量最近的*抹掉,剩下的类型)
    再举个例子
    int **p;//即sizeof(int *) = 4;

至于步长的概念,我们在之后的数组指针或者指针数组还会提到,大家不理解也可以,到时候也会再详细讲解。

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

猜你喜欢

转载自blog.csdn.net/qq_40544107/article/details/113461382
今日推荐