C/C++中可以对指针进行进行算术运算,但其如何解释呢? 有如下的程序:
#include <stdio.h>
int main()
{
int* a = reinterpret_cast<int*>(0x100);
a+=4;
printf("a = %p/n",a);
double* b = reinterpret_cast<double*>(0x200);
b+=4;
printf("b = %p/n",b);
return 0;
}
运行后输出如下:
a=00000110
b=00000220
也就是说a+=4,被解释为a+= 4*sizeof(int),同样b+=4 被解释为b+=4*sizeof(double),
那么是不是说对于如下的定义:
A* B = C; B(+/-)D可以解释为 B(+/-)D*sizeof(A)呢? 且看下面的程序:
#include <stdio.h>
int main()
{
int* a = reinterpret_cast<int*>(0x100);
int* b = reinterpret_cast<int*>(0x200);
a+=b;
printf("a+=b = %p/n",a);
double* c = reinterpret_cast<double*>(0x200);
double* d = reinterpret_cast<double*>(0x300);
c+=d;
printf("c+=d = %p/n",c);
return 0;
}
试图编译却出现如下错误:
error C2297: '+=' : illegal, right operand has type 'int *'
error C2114: '+=' : pointer on left; needs integral value on right
这是说两个指针之间不能直接相加了。那么两个指针直接相减可以么? 答案也是否定的。
int main()
{
int* a = reinterpret_cast<int*>(0x100);
int* b = reinterpret_cast<int*>(0x50);
a-=b;
printf("a-=b = %p/n",a);
double* c = reinterpret_cast<double*>(0x200);
double* d = reinterpret_cast<double*>(0x150);
c-=d;
printf("c-=d = %p/n",c);
return 0;
}
error C2297: '-=' : illegal, right operand has type 'int *'
error C2114: '-=' : pointer on left; needs integral value on right
同样指针之间相乘,相除可以么?结果也是否定的。
这是为什么呢?其实指针用于指向一块内存,那么唯一有意义的操作就是前后偏移游历这块内存了,
而偏移的单位是sizeof(指针基础类型)。指针加上获取减去一个整形量N,其实相当于游历指向的这块内存,
也就是相对于内存基地址而作的偏移,偏移量为N*sizeof(指针基础类型)。显然合法的运算就是指针加减
一个整形量,所以而两个指针之间这种运算,指针乘除整形量或者两个指针乘除都是无法编译通过的,
这是内部指针类型的运算符的限制。
有了上面的结论,我们再看下面的代码:
在一个数组a中,a[n]表示第n个元素本身,那么&a[n]就是第n个元素的地址了。
#include <stdio.h>
int main()
{
int a[6] = {1,2,3,4,5,6};
printf("a=%p/n",a);
printf("a[2]=%p/n",&a[2]);
return 0;
}
输出如下:
a=0012ff4c
&a[2]=0012ff54
从数据元素是连续存储的角度出发,上述结果完全正确:(0012ff54-0012ff4c) = 8 也就是
说前面有2个int元素了。下面又有这么个程序,
#include <stdio.h>
int main()
{
int a[6] = {1,2,3,4,5,6};
printf("%d/n",a[&a[3]-&a[1]]);
return 0;
}
它能编译通过么? 按照上面的两个指针不能直接相加减的说法,应该是编译不过了,但事实
是它可以编译过,而且运行结果为3! 这似乎存在了一个矛盾了!&a[3],&a[1] 也是两个
指针啊,为什么他们可以相加减呢? 错!这里偷换了一个概念:指针和地址,虽然指针存储
一块内存的起始地址,但地址不一定就是指针
但上面的运行结果为3,也就表明了&a[3]-&a[1] = 2, 这是怎么得到的呢,很显然是(&a[3]-&a[1])/4
这似乎说明了地址也是有大小的。从某种意义上来说指针算术运算只是地址算术运算的一种特殊形式,
有自己更为严格的限制。