最近在学习c语言的指针与数组,在学习的过程中顺便把指针这章节的部分知识点简要的罗列下,以帮助理解记忆。
两个符号:
1、一元运算符*是间接寻址或间接引用运算符。 当它作用与指针时,将访问指针所指向的对象。
2、&为地址运算符。它只能应用与内存中的对象,即变量与数组元素。它不能作用与表达式、常量或register类型的变量。
指针定义:
指针是一种变量,它是保存变量地址的变量。
指针与地址
通常机器都有一系列的连续编号或编址的存储单元,这些存储单元可以单个进行操纵,也可以连续成组的方式进行操纵。通常情况下,机器的一个字节可以存放一个char类型的数据,两个相邻的字节存储单元可存储一个short(短整型)类型的数据,而4个相邻的字节存储单元便可存储一个long(长整型)类型的数据。指针是能够存放一个地址的一组存储单元(通常为两个或四个字节)。
简单示例:
1 int a = 1, b = 2, c[10];2 int *p; /*p是指向int类型的指针*/
3 p = &a; /*p现在指向a*/
4 b = *p; /*b的值现在为1*/
5 *p = 0; /*a的值现在为0*/
6 p = &c[0]; /*p现在指向c[0]*/
注意:
指针只能指向某种特定类型的对象,也就是说,每个指针都必须指向某种特定的数据类型。而void类型的指针则可以存放指向任何类型的指针,但它不能引用自身。
运算符优先级:
一元运算符*和&的优先级比算术运算符的优先级要高。形如a = *p + 1则执行*p指向的对象的值取出并加1操作,然后再将结果赋值给a。而*p += 1则是将p指向的对象的值加1。
*p += 1 <=>++*p或(*p)++ 一元运算符遵循从右至左的结合顺序。
最后补充一点:
由于指针也是变量,所以在程序中可以直接使用,而不必通过间接引用的方法使用。
指针与函数参数
由于c语言是以传值的方式将参数值传递给被调用函数,因此被调用函数不能直接修改主调用函数中变量的值,即使要修改,也只是修改了变量参数副本的值。
1 /*这是一个错误的示例*/
2 void swap(int x, inty)3 {4 inttemp;5 temp =x;6 x =y;7 y =temp;8 }9
10 /*这个是正确的示例,使用了指针来达到我们所需要的功能*/
11 void swap(int *px, int *py)12 {13 inttemp;14 temp = *px;15 *px = *py;16 *py =temp;17 }
由上例得到的总结 :指针参数使得被调用函数能够访问和修改主调用函数中对象的值。
指针与数组
在c语言中指针与数组的关系十分密切,通过数组下标所能完成的任何操作通过指针都可以实现。用指针编写的程序要比用数组下标编写的程序执行速度快。
int a[10];先定义一个长度为10的数组a,即由10个对象组成的集合,这10个对象存储在相邻的内在区域中,名字分别为a[0]、a[1]…a[9]。a[i]可 表示为该数组的第i个元素。
int *pa;此处声明了一个指向整型类型的指针,
pa = &a[0];则表示pa指向数组a的第0个元素,也就是说pa的值为数组a[0]的地址。
x = *pa;将数组a[0]中的内容复制到变量x中。
如果pa指向数组中某个特定元素pa = &a[i],那么,pa+1将指向下一个元素,pa+i将指向数组当前之后的第i个元素,而pa-i将指向当前数组元素之前的第i个元素。
因此,如果pa指向a[0],那么*(pa+i)引用的是数组a[i]的内容,pa+i存储的是数组元素a[i]的地址。
执行pa = &a[0];后,pa和a具有相同的值,因为数组名所代表的就是该数组最开始的一个元素的地址,所以pa = &a[0] <=> pa = a 而对数组元素a[i]的引用也可以写成*(a+i)。
实际上在c语言中计算a[i]的值时,首先是将其转换成*(a+i)的形式,然后再求值。如果对这两种等价的表示形式分别加地址运算符&,可以知道:&a[i]和a+i的含义是相同的。
总结:
一个通过数组和下标实现的表达式可等价地通过指针或偏移量实现。指针是一个变量,因此在c语言中,pa = a和pa++都是合法的。但数组名不是变量,因此类似a = pa和a++形式的语句都是非法的。
当把数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址。在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个储存地址值的变量。
1 /*strlen函数:返回字符串s的长度*/
2 int strlen(char *s)3 {4 intn;5 for (n = 0; *s != ‘‘; s++)6 n++;7 returnn;8 }
上例中,s是一个指针,所以对其执行自增运算是合法的。指向s++不会影响到strlen函数的调用者中的字符串,它仅对该指针在strlen函数中的私有副本进行自增运算。