指针剖析之指针算术运算

简介:     指针可以进行加/减去一个整数。指针这种运行的意义和通常的数值加减意义不一样,它是指加/减去一个单元的长度。 1、指针算术运算终极案之指针变量自加的实质、 char a[30]; int *p ...

    指针可以进行加/减去一个整数。指针这种运行的意义和通常的数值加减意义不一样,它是指加/减去一个单元的长度。

1、指针算术运算终极案之指针变量自加的实质、


  1. char a[30];
  2. int *p = (int *)a; // 强制类型转换并不会改变a的类型
  3. printf("&p = %p , *p = %p, &a = %pn",&p,p,a);
  4. p++;
  5. printf("&p = %p , (p++) = %p , &a = %pn",&p,p,a);
  6. p++;
  7. printf("&p = %p , (p++) = %p , &a=%pn",&p,p,a);
  8. // 错误的写法 printf("&p = %p , (p++) = %d , &a=%pn",&p,*p,a);


 

image图1、内存操作结果图

    图1的内存操作结果,可以通过图2的图示解释:

image

图2、指针相加操作详细图

 

    图2中,p是int*型指针,被赋char a的地址。然后分别执行了两个p++,注意到p所占据的内存空间始终没有变;唯一变的是p所占据的内存空间里面的值,也就是p++是从数组a起始地址往后增加了4个字节的地址长度。

 

2、指针算术运算终极案例之字符指针与整型指针自加的区别


  1. char a[20] ="I'm a super man!";
  2. char *ptr1 = a;
  3. printf("%sn",a);
  4. ++ptr1;
  5. printf("%16sn",ptr1);
  6. ++ptr1;
  7. printf("%16snn",ptr1);
  8.  
  9. printf("%sn",a);
  10. int *ptr2 = (int *)a;
  11. ++ptr2;
  12. printf("%16sn",ptr2);
  13. ++ptr2;
  14. printf("%16sn",ptr2);


image

图3

 

image

图4

    由上面程序可以看出,对于char *ptr1,int *ptr2,进行p++,都是以字符单元和整型单元为单位进行增加。

 

3、指针运算之越界问题


  1. char a[20] ="I'm a super man!";
  2. printf("%sn",a);
  3. int *ptr2 = (int *)a;
  4. ++ptr2;
  5. printf("%16sn",ptr2);
  6. ptr2 = ptr2+4;
  7. printf("%16sn",ptr2);


image 图5

    图5的运行结果,证明了一个整型指针的加减是以sizeof(int)个字节为单元进行的。ptr2+4明显超出了数据a[20]的边界,所以读出的是一堆乱码。注意,这里程序并没有报错,也就证明语法上是允许这样写的。

 

4、指针运算的典型陷阱


  1. char a[20] ="I'm a super man!";
  2. char *p = a;
  3. char **ptr = &p;
  4. printf("**ptr = %cn",**ptr);
  5. ptr++;
  6. printf("**ptr = %cn",**ptr);


上面这段代码,或许有些人会认为第二个printf输出的是[’],果真是吗?

 

image图6

 

    由图6可知,ptr是一个指向指针的指针变量。它的值是一个32位的地址,ptr++,即就是进行ptr+sizeof(char*)=ptr+4,得到的是一个0x0012ff44的地址。这是一个什么地址?一个非法的地址!这时候执行printf("**ptr = %c\n",**ptr);,肯定会报错,如图7.

image

图7

 

    所以,一个指针变量加上或减去一个整数n,实质是等于指针变量的值+/- sizeof(type *)*n,即移动sizeof(type *)*n个单元

    另外,两个指针不能进行加法运算,进行加法后,得到的结果指针一个不知所向的地方,没有意义。两个指针可以进行减法操作,但必须类型相同,一般用在数组方面。



参考文献

《让你不再害怕指针》,作者 佚名,向原作者致敬!

相关文章
|
编译器
C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(上)
C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(上)
|
编译器
C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(下)
C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(下)
119 0
|
12月前
|
人工智能
魔法指针 之 指针变量的意义 指针运算
魔法指针 之 指针变量的意义 指针运算
71 0
|
C语言
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)1
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)
248 51
|
存储 C++
有关【指针运算】的经典笔试题
有关【指针运算】的经典笔试题
90 4
在C和C++中,指针的算术操作
在C和C++中,指针的算术操作
|
C语言 C++
C语言:指针运算笔试题解析(包括令人费解的指针题目)
C语言:指针运算笔试题解析(包括令人费解的指针题目)
148 1
|
存储 人工智能 编译器
【重学C++】【指针】一文看透:指针中容易混淆的四个概念、算数运算以及使用场景中容易忽视的细节
【重学C++】【指针】一文看透:指针中容易混淆的四个概念、算数运算以及使用场景中容易忽视的细节
199 1
|
编译器
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)3
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)
111 8
|
编译器
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)2
【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)
107 8