指针操作

C提供了6种基本的指针操作,下面的程序演示这些操作:

//ptr_ops.c --指针操作

#include
int main(void)
{
	int urn[5] = { 100,200,300,400,500 };
	int * ptr1, *ptr2, *ptr3;
	ptr1 = urn;//把一个地址赋给指针
	ptr2 = &urn[2]; //同上
				   //取得指针指向的值
				   //并且得到指针的地址
	printf("pointer value,dereferenced pointer,pointer address:\n");
	printf("ptr1=%p,*ptr=%d,&ptr1=%p\n", ptr1, *ptr1, &ptr1);
	/*指针加法*/
	ptr3 = ptr1 + 4;
	printf("\n adding an int to a pointer:\n");
	printf("ptr1+4=%p,*(ptr4+3)=%d\n", ptr1 + 4, *(ptr1 + 3));
	ptr1++;//递增指针
	printf("\n values after ptr1++\n");
	printf("ptr1=%p,*ptr1=%d,&ptr1=%p\n", ptr1, *ptr1, &ptr1);
	ptr2--;//递减指针
	printf("\n values after --ptr2\n");
	printf("ptr2=%p,*ptr2=%d,&ptr=%p\n", ptr2, *ptr2, &ptr2);
	--ptr1; //恢复为初始值
	++ptr2; //恢复为初始值
	printf("\n pointer reset to orignal values:\n");
	printf("ptr1=%p,ptr2=%p\n", ptr1, ptr2); 
	//一个指针减去另一个指针
	printf("\n subtracting one pointer  from another:\n");
	printf("ptr2=%p,ptr1=%p,ptr2-ptr1=%d\n", ptr2, ptr1, ptr2 - ptr1);
	//一个指针减去一个整数
	printf("\n subtracting an int from a pointer:\n");
	printf("ptr3=%p,ptr3-2=%p\n", ptr3, ptr3 - 2);
	return 0;
}

输出结果如下:
 

pointer value,dereferenced pointer,pointer address:
ptr1=0101FDA4,*ptr=100,&ptr1=0101FD98

 adding an int to a pointer:
ptr1+4=0101FDB4,*(ptr4+3)=400

 values after ptr1++
ptr1=0101FDA8,*ptr1=200,&ptr1=0101FD98

 values after --ptr2
ptr2=0101FDA8,*ptr2=200,&ptr=0101FD8C

 pointer reset to orignal values:
ptr1=0101FDA4,ptr2=0101FDAC

 subtracting one pointer  from another:
ptr2=0101FDAC,ptr1=0101FDA4,ptr2-ptr1=2

 subtracting an int from a pointer:
ptr3=0101FDB4,ptr3-2=0101FDAC
下面的列表描述了可对指针变量执行的基本操作:

  • 赋值:可以把一个地址赋给指针。通常使用数组名或地址运算符&来进行地址赋值。本例中,把数组urn的起始地址赋给ptr1,该地址的编号为0101FDA4的内存单元。变量ptr2得到的是数组第三个也就是最后一个元素(urn[2])的地址。注意:地址应该和指针类型兼容。也就是说不能把一个double类型的指针赋给一个指向int的指针。
  • 求值:运算符*可以取出指针指向的地址中存储的数值。因此*ptr1开始为100,即存储在地址0101FDA4中的值。
  • 取指针地址:指针变量同其他变量一按具有地址和数值,使用运算符&可以得到存储指针本身的地址。在本例中,ptr1被存储在内存地址0101FD98中,该内存单元的内容是0101FDA4,即urn的地址。
  • 将一个整数加给指针:可以使用+运算符把一个整数加给一个指针,或者把一个指针加给一个正数。两种情况下,这个整数都会和指针所指类型的字节数相乘,然后得到的结果会加到初始地址上。于是,ptr+4的结果等同于&urn[4]。如果相加的结果超出了初始指针所指向的数组的范围,那么这个结果是不确定的,除非超出数组最后一个元素的地址能够确保有效。
  • 增加指针的值:可以通过一般的加法或增量运算符来增加一个指针的值。对指向某数组元素的指针做增量运算,可以让指针指向该数组的下一个元素,因此,ptr1++运算把ptr1加上数值4(我们系统上的int为4个字节),使ptr1指向urn[1]。现在ptr1的值是0101FDA8,*ptr的数值为200,但是需要注意的是,ptr1本身的地址仍然是0101FD98。
  • 从指针中减去一个整数:可以使用“-”运算符来从一个指针减去一个整数。指针必须是第一个操作数,或者是一个指向整数的指针,这个1整数都会和指针所指类型的字节数相乘,然后所得的结果会从初始号地址中减掉。于是,ptr3-2的结果等同于&urn[2],因为ptr3是指向&urn[4]的。如果相减的结果超出了初始指针所指向的数组的范围,那么这个结果是不确定的,除非超出数组最后一个元素的地址能够保证有效。
  • 减小指针的值:指针当然可以做减量运算,在本例中,ptr2自减1之后,它不再指向第三个元素,而是指向第二个数组元素。请注意,我们可以使用前缀和后缀形式的增量和减量运算符。对指针ptr1和ptr2都指向同一个元素urn[1],直到它们被重置。
  • 求差值:可以求出两个指针间的差值。通常对分别指向同一个数组内的两个元素的指针求差值,以求出元素之间的距离。差值的单位是相应类型的大小。在本例中,ptr2-ptr1的值为2,表示指针所指向对象之间的距离是2个int数值大小,而不是两个字节。有效指针差值运算的前提是参加运算的两个指针之间的差值运算可能会得到一个数值结果,但也可能会导致一个运行时的错误。
  • 比较:可以使用关系运算符来比较两个指针的值,前提是两个指针具有相同的类型。

C保证指向数组元素的指针和指向数组后的第一个地址的指针都是有效的。但是如果指针在进行了增量或减量运算后超出这个范围,后果将是未知的。另外,可以对指向一个数组元素的指针进行取值运算,但是不能对指向数组后第一个元素的指针进行取值运算,尽管这样的指针是合法的。

对未初始化的指针取值

使用指针,有一个规则需要注意:不能对未初始化的指针取值。例如下面的例子:
 

int * pt;    //未初始化的指针
* pt=5;    //一个可怕的错误

为什么这样的代码危害极大?这段程序的第二行表示把数值5存储在pt指向的地址。但是由于pt没有被初始化,因此它的值是随机的,不知道5会被存储到哪儿。这个位置也许对系统危害不大,但也许会覆盖程序数据或者代码,甚至导致程序崩溃。切记:当创建一个指针时,系统只分配用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。因此在使用指针之前,必须给它赋予一个已分配的内存地址。

你可能感兴趣的:(C)