ANSI C 使用 void* 作为通用指针类型.
5.1 指针与地址
指针 p 指向 char 类型的 c:

p = &c;
&只能作用于内存中的对象, 即变量和数组元素, 不能作用于表达式, 常量或 register 类型的变量.*间接寻址或间接引用运算符

int *ip; // 强调 *p 的结果是 int
double *dp, atof(char *); // *dp 和 atof() 都是 double 类型
void * 不能间接引用自身.
iq = ip // iq 与 ip 指向相同的地方
5.2 指针与函数参数
void swap(int *px, int *py) {
int temp;
temp = *px;
*px = *py;
*py = temp;
}



5.3 指针与数组
int a[10];

int *pa;
pa = &a[0];

*(pa + i)

int a[3];
int *p;
p = a; // 合法
int b;
b = *(a+1); // 合法
int c;
c = p[1]; // 合法
p++; // 合法
a = p; // 非法
a++ // 非法
在函数定义中, char s[] 与 char *s 等价.
可以利用地址传递子数组给函数:
f(&a[2]);
f(a+2);
如果确信元素在数组中存在, 也可以使用负数:
p[-1];
5.4 地址算术运算
#define ALLOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;
char *alloc(int n) {
if (allocbuf + ALLOCSIZE - allocp >= n) {
allocp += n;
return allocp - n; // 被分配内存的起始地址
} else {
return 0;
}
}
void afree(char *p) {
if (p >= allocbuf && p < allocbuf + ALLOCSIZE) {
allocp = p;
}
}

int *p; // 此时 p == 0;
指针不能与整数相互转换, (除了0).
- 指针可以与常量0进行比较
- C 中的 NULL 定义在
中
在计算 p+n 时, n 将根据 p 指向的对象的长度按比例缩放, p 指向的对象的长度取决于 p 的声明.
总结:

5.5 字符指针与函数
char *pmessage;
pmessage = "now is the time";
字符指针与字符数组的区别:
#include <stdio.h>
int main() {
char a[] = "abc";
a = "def"; // 编译错误
char *p = "abc";
p = "def";
p[0] = 'g'; // 运行时错误
printf("%s\n", p);
printf("%s\n", p[1]); // 编译时警告, 运行时错误
printf("%c\n", p[1]); // %c
printf("%c\n", *(++p));
return 0;
}

赋值字符串的精简函数:
void strcpy(char *s, char *t) {
while(*s++ = *t++)
;
}
字符串比较的精简函数:
int strcmp(char *s, char *t) {
// 只要 s[i] != t[i], 循环就退出了,
// 不用担心 len(s) != len(t)
for (; *s == *t; s++, t++) {
if (*s == '\0') {
return 0;
}
}
return *s - *t;
}
字符栈操作的精简写法:
*p++ = val; // 入栈
val = *--p; // 出栈
5.6 指针数组以及指向指针的指针
对文本行排序:
- 所有文本行存储在一个大字符串数组中
- 交换的是每个文本行的指针
- 这些指针存储在数组中 (指针数组)






5.7 多维数组


逻辑表达式的结果只可能是0或1.
声明需要二维数组参数的函数的方式:
- 必须指明列数
f(int daytab[2][13]) {}
f(int daytab[][13]) {}
// [] 的优先级比 * 高, 所以使用 ()
// int *daytab[13] 指向整型对象的指针
f(int (*daytab)[13]) {} // 指向一维数组
5.8 指针数组的初始化
编译器确定数组长度:

5.9 指针与多维数组
int a[10][20]; // 分配了200个空间
int *b[10]; // 分配了10个指针
矩阵下标公式:
20*row + col
指针数组的优点:
- 每行所具有的元素数可以不同
字符串指针数组:

二维数组:

注意存储形式.
5.10 命令行参数




format 字符串可以是表达式:
printf((argc > 1) ? "%s " : "%s", *++argv);

添加命令行 flag:
[]的优先级比*++都高*++的优先级相同

5.11 指向函数的指针
排序通常包括3个部分:
- 比较
- 交换
- 算法



错误的写法:
int *comp(void *, void *)


5.12 复杂声明
C 语言的声明不能从左至右阅读.
// 函数声明, 返回 int *
int *f();
// 指针声明, 指向函数, 返回 int
int (*pf)();
