1.对于指针p分清楚printf p/&p/*p这几个储存的区别(对指针内部储存操作/对指针地址操作/对指针内部储存地址指向变量操作)
2.我们使用指针进行间接访问的赋值,因为简单的赋值不一定可行,例如在链表的插入中。在那些函数我们无法使用简单的赋值,因为变量名在函数的作用域内部是未知的。函数所拥有的只是一个指向需要修改的内存位置的指针。
3.
int f();
f为一个函数,返回值为一个整数。
int *f();
f为一个函数,返回值为一个指向整型的指针。
int (*f)();
f是一个函数指针,返回值为一个整型值。
int *(*f)();
f为一个函数指针,返回值为一个整型指针。
int f[];//长度暂时未标明
f为一个整型数组。(如果它的属性是external或是作用函数的参数,即使在声明时未标注长度,也仍是合法)
int f()[];
非法,函数只能返回标量值,不能返回数组。
int f[]();
非法,因为数组元素必须要有相同的长度,而不同函数可能具有不同的长度。
int (*f[])();
f为某种类型的指针数组,返回值为整型值。
int *(*f[])();
f为指针数组,返回值为整型指针。
4.函数名被使用时,总是由编译器把它转换成函数指针,在用指针指向函数时,可以不用&符号,这个符号只是说明要操作的内容。
5.回调函数:
void Find(char *s); int main(void) { void (*pointer)(char *s); pointer=Find; pointer("hello world\n"); return 0; } void Find(char *s) { printf(s); }
6.为了使用switch语句,表示操作符的代码必须是整数。如果它们是从零开始连续的整数,我们可以使用转换表来实现相同的任务。转换表就是一个函数指针数组。
这里有一个计算器:
1 switch(operation) 2 { 3 case ADD: 4 result=add(a,b);break; 5 case SUB: 6 result=sub(a,b);break; 7 case MUL: 8 result=mul(a,b);break; 9 case DIV: 10 result=div(a,b);break; 11 ..... 12 }
如果要实现的操作很多,那么这个长度就太长,复杂。
建立转移表
double (*operation_fun[])(double,double)={add,sub,mul,div,......};
这个相当于:
1 double add(double,double); 2 double sub(double,double); 3 double mul(double,double); 4 double div(double,double); 5 ......
调用转移表:
double result; result=operation_fun[operation](a,b);
7.main函数具有两个形参,一个通常称为argc,它表示命令行参数的数目。第二个通常称为argv,它指向一组参数数值。有些操作系统向main函数传递第三个参数,他是指向环境变量列表以及他们的值的指针。
int main(int argc ,char **argv)
8.printf从右到左执行
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) { 5 int i=3; 6 printf("%d %d %d %d",i++,++i,i++,i++);//第一个可以换成i++
7 return 0; 8 }
打印i和++i,i是随整体变化的,不管是前面还是后面变化了,它都会变。
而i++是到现在就行(从右到左)
9.当一个字符串常量出现于表达式中时,它的值是一个指针常量。
编译器将这些指定字符的一份拷贝存储在某个位置,并存储一个指向第一个字符的指针。但是,当数组名用于表达式中时,它们的值也是指针常量。
"xyz"+1;
将“xyz”看成指针,也就是指针值+1打印出的是y。
"xyz";//指向指针所指向的内容,x "xyz"[2];//z