C指针

In C, all function arguments are passed "by value".
所有传递给函数的参数都是按值传递。
swap(&a, &b);
void swap(int *px, int *py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}

int a[10], *pa;
pa = a; 等价于 pa = &a[0];
数组名就是数组第一个元素的地址。

在计算数组元素 a[i] 的值时,C语言实际上将其转换为 *(a+i) 的形式。
因此,&a[i] 与 a+i 等价,pa[i] 与 *(pa+i) 等价。

当把数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址。
void func(int *a) {...}
void func(int a[]) {...}
参数写成指针形式还是数组形式对编译器来说没区别,都表示这个参数是指针,之所以规定两种形式是为了给读代码的人提供有用的信息,如果这个参数指向一个元素,通常写成指针的形式,如果这个参数指向一串元素中的首元素,则经常写成数组的形式。

只有两指针指向同一个数组的元素时,才允许指针相减,p2 - p1 == j - i。
所有指针算术运算都会自动考虑它指向的对象的长度。

char amessage[] = "123456789";
char *pmessage = "123456789";
amessage 是一个仅仅足以存放初始化字符串以及'\0'的一维数组。
pmessage 指向一个字符串常量, 不能修改字符串内容,不如改为 const char *pmessage = "123456789";

*p++ = val;
val = *--p;
是进栈和出栈的标准用法

const char *name[] = {"Illegal month", "Jan", "Feb", "Mar"};
char name[][15] = {"Illegal month", "Jan", "Feb", "Mar"};
指针数组在处理不同长度字符串时,省了不必要的空间。

用结构体指针做函数参数
结构体作为函数参数时也是值传递,会复制整个结构,效率不高。

在使用指针前,要判断是否为空指针。

传递给free()的指针必须是malloc等返回的指针。
// 释放链表
for (p = head; p != NULL; p = p->next)	/* Wrong! */
	free(p);

for (p = head; p != NULL; p = q) {
	q = p->next;
	free(p);
}


下标绝对不会比指针更有效率,但指针有时会比下标更有效率。

函数名:函数代码在内存中代码段的地址。
typedef int (*fun_t)(int, int); /* fun_t为函数指针的类型 */
int *func(void); /* 返回一个指向int类型的指针 */
double (*oper_func[]) = {add, sub, ...}; /* 函数指针数组 */

void指针可以指向任何类型的变量。
int n, *p;
void *vp;
vp = (void *)&n;
p = (int *)vp;

int matrix[3][10];
matrix 指向包含10个整型元素的数组指针
matrix+1 同上,指向第二行
*(matrix+1) 指向整型的指针
*(matrix+1)+5 同上,向后移5个元素
*(*(matrix+1)+5) 元素值

int (*p)[10] = &matrix[0];
int (*p)[10] = matrix; 指向数组的指针
int *p[10]; 指针数组,元素为指针

int calendar[12][31];
int (*monthp)[31];
for (monthp = calendar; monthp < &calendar[12]; monthp++) {
	int *dayp;
	for (dayp = *monthp; dayp < &(*monthp)[31]; dayp++)
		*dayp = 0;
}

主要摘自《The C Programming Language》 Chapter 5 - Pointers and Arrays
《Pointers on C》
《C Traps and Pitfalls》

你可能感兴趣的:(c)