指针变量
type *p : p是指针变量,类型是type*,用来存储地址。
type决定了通过这个指针变量访问内存解析内存数据的方式。
1 . 访问内存的大小。
2. 内存中二进制数据所解析的类型。
3. 加减法的偏移量p+1。
注意点
- 数组做形参时 数组名退化为普通指针
- switch(表达式) int char short
表达式的结果的类型可以是 整数类型,枚举类型,或者类类型(但该类需要有单一的转换到整数类型或(可以是字符类型,但不能是浮点类型、字符串、指针类型等) - static
- 修饰局部变量:让局部变量的生存周期变为全局的。
- 修饰全局变量:让全局变量只能在本文件中使用
- 修饰函数:让函数只能在本文件中使用。
函数调用过程
我们把调用其他函数的函数称为主调函数(主函数),把被调用的函数称为被调函数(子函数),那么函数的调用流程如下:
① 按顺序执行主调函数中的语句,直到调用被调函数前的语句为止;
② 跳转到被调函数中执行,一直到被调函数正常结束,或是调用return 返回;
③ 返回主调函数中,从被调函数后的第一个语句开始继续开始执行。每个函数被调用时都有自己的栈空间,这块栈空间是私有的,只归本函数使用,用于存储参数和局部变量。当函数调用结束(代码结束或是遇到return 语句)时,这块栈空间会被编译器自动回收,存储在上面的数据将不能再被使用。
函数的声明
当函数的定义出现在调用之前时,函数可以正常调用。而当函数的定义出现在调用之后时,函数的调用就会出现无法识别的问题(GCC 编译器需要添加 -Wall 选项才可以看到错误提示信息)。
指针类型的返回值
对于指针类型的返回值,有一点要非常注意,不可以返回指向栈内存的指针,因为栈空间在函数返回后就已经被回收了。
递归函数
函数可以调用自己调用自己,函数自己调用自己称为函数的递归。函数递归尤其要注意的一点是,递归需要有一个终止条件,否则函数一直递归下去,栈空间终会被消耗完,导致程序的段错误。
- 不使用任何变量求字符串长度
int my_strlen(char *str)
{
if(*str == ‘\0’)
{
return 0;
}
else
{
return (1 + my_strlen(++str));
}
}
- 递归打印十进制数的n进制(二进制举例)
#define SCALE 2
void base_conversion(int num)
{
if(num < SCALE)
{
printf("%d", num);
return;
}
else
{
base_conversion(num / SCALE);
printf("%d", num % SCALE);
}
}
函数指针
- 每个函数在经过编译后最终都会形成一段二进制代码,而这些代码在程序运行时也会载入内存,所以每个函数都会在内存中有一个存储的地址,通过改地址便可调用函数。
- 函数的地址就是函数名,这点与数组类似。
int add(int a , int b)
{
return a + b;
}
int (*padd)(int a, int b); //定义函数指针
padd = add; //给函数指针赋值
padd(3, 2); //通过函数指针调用函数
回调函数
如果某个函数的参数中带有函数指针,那么我们称这个函数为回调函数。同样可以完成对函数的调用。
int add(int a, int b)
{
return a + b;
}
int callback(int num1, int num2, int (*pfun)(int, int)) //回调函数
{
return pfun(num1, num2);
}