关于指针运算的浅析

1708阅读 0评论2011-11-23 jonas_mao
分类:C/C++

对于指针的运算,其实在编码过程中很常见,我们一般的算法实现里面经常要用到的比如:char *p; p++;
p--;这种尤为常见。因为都是char *类型的,sizeof(char)类型是1,所以感觉比较符合我们的一般十进制的运算,因而也就没有怎么去理解关于指针运算的真实。
 
先看下面一段代码:
  1. #include <stdio.h>

  2. int main (void)
  3. {
  4.   int *p1 = (int *)0x0011;
  5.   int *p2 = (int *)0x0001;
  6.   
  7.   printf ("\n p1 = %p, p2 = %p", p1, p2);
  8.   printf ("\n p = %d", (p1 - p2));
  9.   
  10.   if ((p2 + 16) == p1)
  11.     printf("\n (p2 + 16) == p1");
  12.     
  13.   if ((p2 + 4) == p1)
  14.     printf("\n (p2 + 4) == p1");
  15.     
  16.   return 0;
  17. }

上面这段代码的输出是:(本人公司用的是GCC编译的)

由输出可以看出,p1 = 0x11; p2 = 0x01;

两者相减的话应该是 p1-p2 = 0x11 - 0x01 = 0x10;

0x10 化为十进制是 16, 而结果是 p = 4;  刚好是16 \ sizeof (int) ;

这里说明p1 和 p2之间相差了 4个 sizeof(int)个单位, 而 16 则是这 4个单位的十进制计算的值。

所以后面的 if 条件语句中满足的应该是第二个。输出 (p2 + 4) == p1;而不是 (p2 + 16) == p1;

这里需要注意的是指针和指针之间不能够进行相加:比如 这里 如果p1 + p2 则会出现这样的编译错误:

error: invalid operands to binary +

其实我们可以想象在一段内存中

!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!

p2(0x01)                                        p1(0x11)

p2 和 p1 分别指的是内存中的地址, 这两个地址相加 结果应该是什么,是直接两者的内存地址相加?还是直接是p1? 这些都不是,其实我们不难看出,我们看到的运算基本上是针对那些基本数据类型的。而指针的这种相加不知怎么理解,或许正因为不好怎么定义,所以C中并不认可这种运算。

那么指针的相减又为什么可以? 通过上面的代码可得其实两个指针的相减是在计算两个指针之间的度量,可以认为是距离。

对于指针和常数的加减运算,可以理解为是在该指针所指的内存地址的基础上在加上 (常数*度量)个字节,结果还是一个指针。

上面讲的都是相同类型指针之间的运算。下面补充不同类型的指针的运算。

补充不同类型之间的指针的运算:

  1. #include <stdio.h>

  2. int main (void)
  3. {
  4.   char *p = (char *) 0x009;
  5.   int *p1 = (int *)0x0001;
  6.   
  7.  // printf("\n p - p1 = %d", p - p2); //这里如果两个类型不一样是通不过编译的
  8.   printf("\n p - p1 = %d", (int *)p - p1);
  9.   printf("\n p - p1 = %d", p - (char *)p1);
  10.   return 0;
  11. }

输出结果为:

      

 

 

上一篇:怎样花两年时间去面试一个人
下一篇:关于 volatile 关键字