一、指针与地址
机器的存储器通常由连续编号或连续编址的存储单元序列组成,这些存储单元可以以单个的或相连成组的方式操纵。指针由能存放一个地址的一组存储单元构成。
一元运算符&用于取一个对象的地址。该操作符只能应用于内存中的对象(即变量和数组元素),它不能对表达式、常量和寄存器变量进行取址操作。
一元运算符*用于间接寻址或间接引用运算符,当它应用于指针时,将访问指针所访问的对象。
注意:指针只能指向一个特定类型的对象,即每个指针对象都有一个确定的数据类型。(例外是:指向void类型的指针可转换成指向任何对象类型的指针,当它不能间接引用它自身。)
二、指针与函数变元
C语言以传值方式将变元传递给函数。
三、指针与数组
数组下标所能完成的任何运算都可以用指针来实现。一般而言,指针运算比数组下标运算的速度快,当代码可读性较差。
下标和指针运算有着很密切的对应关系。按照定义,一个类型为数组的变量或表达式的值是该数组的第0个元素的地址。在求数组元素a[i]值时,C语言实际上先将其转换成成*(a+i)的形式然后求值,因此a[i]和*(a+i)是等价的,从而&a[i]和a+i是等价的。因此,一个用数组和下标实现的表达式可等价地用指针和偏移量来实现。
但是二者仍然有区别:指针是变量,当数组名字不是变量。
在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。它的类型取决于数组元素的类型:如果是int类型,那么数组名的类型就是“指向int的常量指针”;如果是其他类型,那么数组名的类型就是“指向其他类型的常量指针”。
数组具有和指针完全不同的特征,如:数组具有确定数量的元素,而指针只是一个标量值。编译器用数组名来记住这些属性。只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量。注意这个值是指针常量,而不是指针变量,不能修改常量的值。
只有在两种场合,数组名并不是用指针常量来标识:
- 当数组名作为sizeof操作符时
- 当数组名作为单目操作符&的操作数时
对于指针与下标运算符,事例如下:
int array[10];
2[array] = 5;
array[2] = 5;
以上二者是等价的,编译器都会把它翻译成:*(array+2) = 5;
另外从效率上讲,下标决不会比指针更有效率,但指针有时会比下标更有效率。从而相关结论如下:
- 当要根据某个固定数目的增量在一个数组中移动时,使用指针变量将比使用下标产生效率更高的代码,当这个增量为1并且机器具有地址自动增量模型时,尤其突出。
- 声明为寄存器变量的指针通常比位于静态内存和堆栈中指针效率更高,具体提高的幅度取决于所使用的机器。
- 如果可以通过测试一些已经初始化并经过调整的内容来判断循环是否应该中止,那么就不需要使用一个单独的计数器。
- 那些必须在运行时求值的表达式较之诸如&array[size]或array+size这样的常量表达式往往代价更高。
C语言将指针、数组和地址的算术运算集成在一起是该语言的一大特色。C语言保证0不是数据的有效地址。指针与整数不能相互转换,但0例外:常量0可以赋给指针,指针也可以和0进行比较。(即NULL)
指针的算术运算具有一致性,所有的指针运算都会自动考虑它所指向的对象的大小。
有效的指针运算包括:
(1)、相同类型指针之间的赋值运算
(2)、指针值加或减一个整数值的运算
(3)、指向相同数组中的元素的指针之间的减或比较运算
(4)、将指针赋0或指针与0之间的比较运算
所有除了以上的其他形式的指针运算均非法,如:
(1)、指针间的加法、乘法、除法、移位或屏蔽运算
(2)、指针值加单、双精度浮点数的运算
(3)、除了void*类型指针以外,不经强制类型转换就将指向一种类型对象的指针赋给指向另一种类型对象的指针的运算。
五、字符指针和函数
六、指针数组和指向指针的指针
七、多维数组
总结(复杂说明)
char **argv:指向字符指针的指针
int (*daytab)[13]:指向有13个整数类型元素组成的一维数组的指针
int *daytab[13]:由13个指向整数类型对象的指针组成的一维数组
void *comp():返回值为指向通用类型的指针的函数
void (*comp)():指向返回值为void的函数的指针
char (*(*x())[])():返回值为指向一维数组的指针的函数,该一维数组由指向返回字符类型的函数的指针组成。
char (*(*x[3])())[5]:x由3个指向函数的指针组成的一维数组,该函数返回指向由5个字符组成的一维数组的指针。
说明语法形式:
说明符: 可选的*序列 直接说明符
直接说明符:名字
(说明符)
直接说明符()
直接说明符[可选的大小]
即:换句话说,说明符就是直接说明符,其前面也许带有*号。直接说明符可以是名字、由一对圆括号括住的说明符、后面跟有一对圆括号的直接说明符或后面跟有由方括号括住可选大小的直接说明符。