算术运算
是不是对指针的任何运算都是合法的呢?答案是它可以执行某些运算,但并非所有的运算都合法
。除了加法运算之外,你还可以对指针执行一些其他运算,但并不是很多。(乘法,除法就不可以)
指针加上一个整数的结果是另一个指针。
问题是,它指向哪里?如果你将一个字符指针加1,运算结果**产生的指针指向内存中的下一个字符。
**float占据的内存空间不止1个字节,如果你将一个指向float的指针加1,将会发生什么?它会不会指向该float值内部的某个字节呢?
答案是否定的。当一个指针和一个整数量进行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整。
这个“合适的大小”就是指针所指向类型的大小,“调整”就是把整数值和“合适的大小”相乘。为了更好的说明,试想在某台机器上,float占据4个字节。在计算float型指针加3的表达式时候,这个3将根据float类型的大小(此例中为4)进行调整(相乘),这样实际上加到指针上的整型值为12。
把3与指针相加使指针的值增加3个float的大小,而不是3个字节。这个行为较之获得一个指向一个float值内部某个位置的指针把3与指针相加使指针的值增加3个float的大小,而不是3个字节。这个行为较之获得一个指向一个float值内部某个位置的指针更为合理。下表包含了一些加法运算的例子。调整的美感在于指针算法并不依赖于指针的类型。换句话说,如果p是个指向float的指针,那么p+1就指向下一个float,其他类型也是如此。
C的指针的算术运算只局限于两种形式。
第一种形式是:指针+-整数 标准定义这种形式只能用于指向数组中某个元素的指针,如图所示:
并且这类表达式的结果类型也是指针
。这种形式也适用于使用malloc函数动态分配获得的内存。
对一个指针加1使它指向数组中的下一个元素,加5使它向右移动5个元素的位置,依次类推。把一个指针减去3使它向左移动3个元素的位置。
第二种类型的指针运算具有如下的形式:指针—指针
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针
,如下所示:
两个指针相减的结果的类型是ptrdiff_t,它是一种有符合整数类型。减法运算的值是两个指针在内存中的距离是指针的本身
(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。
如果两个指针所指向的不是同一个数组中的元素,那么它们之间相减的结果是未定义的。
程序员无从知道两个数组在内存中的相对位置,如果不知道这一点,两个指针之间的距离就毫无意义。
举个例子:
#include <stdio.h>
int main(){
int a = 10, *pa = &a;
double b = 99.9, *pb = &b;
char c = '@', *pc = &c;
//最初的值
printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c); //存储空间的地址值
printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);//指针的值
//加法运算
pa += 1; pb += 1; pc += 1;
printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc); //int为4个字节,double为2个字节,char为1个字节
//减法运算
pa -= 2; pb -= 2; pc -= 2;
printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
return 0;
}
同一个数组中两个指针相减例子:
#include<stdio.h>
int main()
{
int a[10] = { 3,5,2,6,4,3,6,4,3 };
int *s = &a[3], *f = &a[7];
printf("*f-*s=%d", f - s);
}
关系运算:
只有当两个指针指向同一个数组中的元素时
,才能进行关系运算。
当指针p和指针q指向同一数组中的元素时,
则: (可以用在if判断里面作为条件)
p<q 当p所指的元素在q所指的元素之前时,表达式的值为1;反之为0。
P>q 当p所指的元素在q所指的元素之后时,表达式的值为1;反之为0。
p==q 当p和q指向同一元素时,表达式的值为1;反之为0。
p!=q 当p和q不指向同一元素时,表达式的值为1;反之为0。
举例:
编写程序将一个字符串反向。
#include <stdio.h>
void main( )
{
char str[50], *p, *s, c;
printf("Enter string:");
gets(str); //从键盘输入字符
p=s=str; //将指针初始化
while ( *p )
{
p++; //将p指向字符串最后
}
p--;//将p指针指向最后一个字符,原来指向最后一个的后面
while ( s<p ) // 判断地址
{
c = *s;
*s++ = *p;
*p-- = c;
}
puts(str);
下面是分步调试的结果: