5.1 指针与地址
指针是一种保存变量地址的变量 ANSI C使用类型void*(指向void的指针)代替char *作为通用指针的类型 一元运算符&可用于取一个对象的地址: p = &c 把C的地址赋值给变量p,我们称p为指向c的指针.地址运算符&只能应用于内存中的对象,即变量与数组元素. 不能作用于表达式 常量或register变量 一元运算符*是间接寻址或间接引用运算符.当它作用于指针时,将访问指针所指向的对象 由于指针也是变量,所以在程序中可以直接使用,而不必通过间接引用的方法使用
5.2 指针与函数参数
C语言是以传值的方式将参数传递给被调用函数,因此被调用函数不能直接修改主调函数中的变量的值
5.3 指针与数组
通过数组下标所能完成的任何操作都可以通过指针来实现 一般来说,用指针编写的程序比用数组编写的程序执行速度快 在计算数组元素a[i]的值时,C语言实际上先将其转换为 *(a+i)的形式,然后再进行求值,因此在程序中这两种形式是等价的 pa[i] = *(pa+i) 一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现 数组名和指针之间有一个不同之处.指针是一个变量 当把数组名传递给一个函数时,实际上传递的是该数组的第一个元素的地址 在被调用函数中,该参数是一个局部变量,因此,数组名必须是一个指针,也就是一个存储地址值的变量.
5.4 地址算术运算
如果P是一个指向数组中某个元素的指针,那么p++将对p进行自增运算并指向下一个元素,而p+=i 将对p进行加i的增量运算,使其指向p当前所指向的元素之后的第i个元素 指针与整数之间不能互相转换,但0是唯一的例外 常量0可以赋值给指针,指针也可以和常量0进行比较 程序中经常用符号常量NULL代替常量0,这样便于清晰地说明常量0是指针的一个特殊值 指针的减法也是有意义的:如果p和q指向相同数组中的元素,且p<q,那么q-p+1就是唯一p和q指向的元素之间的数目 指针的算术运算具有一致性:如果处理的数据类型是比字符型占据更多存储空间的浮点类型,并且p是一个指向浮点类型的指针,那么p++后,p将指向下一个浮点数的地址 有效的指针运算包括相同类型指针之间的赋值运算; 指针同整数之间的加法或减法运算 指向相同数组中元素的两个指针之间的减法或比较运算; 将指针赋值为0或指针与0之间的比较运算 其他所以形式的指针运算都是非法的
5.5 字符指针与函数
字符串常量是一个字符数组 在字符串的内部表示中,字符数组以空字符'\0'结尾,所以,程序可以通过检查空字符找到字符数组的结尾. 字符串常量占据的存储单元也因此比双引号的字符数大1
5.6 指针数组以及指向指针的指针
指针本身也是变量,所以它们也可以像其他变量一样存储在数组中
5.7 多维数组
C语言提供了类似于矩阵的多维数组,但实际上它们并不像指针数组使用的那样广泛
5.8 指针数组的初始化
5.9 指针与多维数组
对于初学者来说,很容易混淆二维数组与指针数组之间的区别
int a[10][20];
int *b[10];
从语法上讲,a[3][4]和b[3][4]都是对一个int对象的合法引用
但是a是一个真正的二维数组,它分配200个int类型的长度存储空间
对b来说该定义仅仅分配了10个指针,并且没有对他们初始化,它们的初始化必须以显示的方式进行,比如静态初始化或通过代码初始化
指针数组的另一个优点在于,数组的每一行长度可以不同
指针数组最频繁的用处是存放不同长度的字符串
5.10 命令行参数
在支持C语言的环境中,可以在程序开始执行时将命令行参数传递给程序. 调用主函数main时,它带有两个参数 第一个参数不是运行时命令行参数的个数(argc) 第二个参数是一个指向字符串数组的指针,其中每个字符串对应一个参数
UNIX系统中C语言程序有一个公共的约定:以负号开头的参数表示一个可选标志或参数.
假定用-X 表示打印所以与模式不匹配的文本行,用-n表示打印行号
5.11 指向函数的指针
在C语言中,函数本身不是变量,但可以定义指向函数的指针 这种类型的指针可以被赋值 存放在数组中,传递给函数以及作为函数的返回值等 //指向函数的指针 int (*comp)(void *,void *); *comp代表一个函数
5.12 复杂声明
C语言的声明不能从左至右阅读,而且使用了太多的圆括号 int *f();//f是一个函数,它返回一个指向int类型的指针 int (*pf)(); //pf是一个指向函数的指针,该函数返回一个int类型的对象 它们之间的含义差别说明,*是一个前缀运算符,其优先级低于(),所以声明中必须使用圆括号以保证正确的结合顺序