指针是保存变量地址
的变量
0x00 指针与地址
一元运算符&
可用于取一个对象的地址,如: p = &c;
, 把变量c的地址赋值给变量p,称p为“指向”c的指针。地址运算符&只能应用于内存中的对象,即变量和数组元素,不能作用于表达式、常量或register类型的变量。
一元运算符*
是间接寻址或间接引用运算符。作用于指针时,将访问指针所指向的对象。
指针声明: int *p;
,该语句表明表达式*ip
的结果是int类型。
0x01 指针与函数参数
由于C语言是以传值的方式将参数值传递给被调用函数,所以调用函数不能直接修改主调函数中变量的值。可以使主调程序将指向所要改变的变量的指针传递给调用函数,这样被调函数可以改变主调函数变量的值。
如:
void swap(int *px, int *py) {
int temp;
temp = *px;
*px = *py;
*py = temp;
}
0x02 指针与数组
通过数组下标所能完成的任意操作都可以通过指针来实现。一般来说用指针编写的程序比用数组下标编写的程序执行速度快。
“指针加1”意味着指针所指向对象的下一个对象。
数组类型的变量或表达式的值是该数组第0个元素的地址。
int *pa, a[10];
pa = &a[0];
pa = a; //等价于pa = &a[0];
一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现。数组名和指针之间的不同之处在于指针是一个变量,而数组名不是,指针可以改变,而数组名不行。
当把数组名传递给一个函数时,实际上传递的是该数组的第一个元素的地址。
在函数定义中,形式参数char s[]
和char *s
是等价的。
0x03 地址算术运算
有效的指针运算包括
- 相同类型指针之间的赋值运算
- 指针同整数之间的加法和减法运算
- 指向相同数组中元素的两个指针间的减法或比较运算
- 将指针赋值为0或指针与0之间的比较运算
0x04 字符指针与函数
字符串常量是一个字符数组。字符串常量可以通过一个指向其第一个元素的指针访问。如:
char *pmessage;
pmessage = "now is the time";
0x05 指针数组以及指向指针的指针
指针数组声明
char *lineptr[MAXLINES];
*lineptr[0]
等价于 **ilneptr
,前者是是一个指针数组,后者是指向指针的指针,但底层是一样的,因为int a[]; a[0] == *a
0x06 多维数组
二维数组是一种特殊的一维数组,它的每个元素也是一个一维数组。
如果将二维数组作为参数传递给函数,在函数的参数声明中必须指明数组的列数。
一般来说,除数组的第一维可以不指定大小外,其余各维都必须明确指定大小。
注意:
// 下面三种声明作用相同
f(int daytab[2][13]) { ... }
f(int daytab[][13]) { ... }
f(int (*daytab)[13])
0x07 指针数组初始化
char *month_name(int n) {
satic char *name[] = {
"Illegal month",
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
...
}
0x08 指针数组与多维数组
int a[10][20];
int *b[10];
a是一个真正的二维数组,它分配了200个int类型长度的存储单元。b定义仅仅分配了10个指针,并且没有初始化。指针数组的一个重要的优点在于,数组的每一行长度可以不同。
0x09 命令行参数
main(int argc, char *argv[])
// argc表示参数数量,argv是参数的指针数组,程序本身是第一个参数
0x10 指向函数的指针
函数本身不是变量,但可以定义指向函数的指针。
// 函数定义
void qsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));
// 函数调用
qsort((void**) lineptr, 0, nlines-1,
(int (*)(void*, void*))(numeric ? numcmp : strcmp));
strcmp和numcp是函数地址, 函数不需要使用地址运算符&
取值,同数组一样。
通用指针类型void *
, 任何类型的指针都可以转换为void *
类型,并且在将它转换回原来的类型时不会丢失信息。
int (*comp)(void *, void *))
声明中表明comp是一个指向函数的指针,*comp
代表一个函数。(*comp)(v[i], v[left])
是对指针函数的调用,其中圆括号必须。