数组类型:
数组类型包括数组元素类型及数组大小
int array[5]的类型为int[5]
定义数组类型:
c中通过typedef为数组类型重命名:
typedef type(name)[size]
之后可以利用该类型定义数组:
typedef int(aint5)[5];
aint5 array;//定义了一个int[5]的数组
数组指针:
数组指针本身是一个指针用于指向一个数组
数组名是数组首元素的起始地址,但并不是数组的起始地址
通过将取地址符&作用于数组名可以得到数组的起始地址
可通过数组类型定义数组指针: ArrayType* pointer;
也可以直接定义:type (*pointer)[n];
pointer为数组指针变量名
type为指向的数组的类型
n为指向的数组的大小
指针数组:
指针数组中本身为一个数组,每个元素类型为指针
定义:type* pArray[n];
二级指针:
指向指针的指针
指针在本质上也是变量
对于指针也同样存在传值调用与传址调用
二维数组与二级指针:
二维数组在内存式中以一维的方排布
二维数组中的第一维是一维数组
二维数组中的第二维才是具体的值
二维数组的数组名可看做常量指针
一维数组名代表数组首元素的地址
int a[5] a的类型为int*
二维数组名同样代表数组首元素的地址
int m[2][5] m的类型为int(*)[5]
C语言中只有一维数组,而且数组大小必须在
编译期就作为常数确定
C语言中的数组元素可是任何类型的数据,即
数组的元素可以是另一个数组
C语言中只有数组的大小和数组首元素的地址
是编译器直接确定的
指针退化
void f(int a[5]); void f(int a[]); void f(int* a);
void g(int a[3][3]); void g(int a[][3]); void g(int (*a)[3]);
注意:C语言中无法向一个函数传递任意的多维数组
为了提供正确的指针运算,必须提供除第一维之外的
所有维长度
限制
一维数组参数 – 必须提供一个标示数组结束位置的长度信息
二维数组参数 – 不能直接传递给函数
三维或更多维数组参数 – 无法使用
函数:
函数的类型由返回值,参数类型和参数个数共同决定
例:int add(int i, int j)的类型为int(int, int)
C语言中通过typedef为函数类型重命名
typedef type name(parameter list)
例:typedef int f(int, int);
typedef void p(int);
函数指针:指向一个函数。
可通过函数类型定义函数指针: FuncType* pointer;
也可以直接定义:type (*pointer)(parameter list);
pointer为函数指针变量名
type为指向函数的返回值类型
parameter list为指向函数的参数类型列表
回调函数;回调函数是利用函数指针实现的一种调用机制
回调机制原理
调用者不知道具体事件发生的时候需要调用的具体函数
被调函数不知道何时被调用,只知道被调用后需要完成的任务
当具体事件发生时,调用者通过函数指针调用具体函数
回调机制的将调用者和被调函数分开,两者互不依赖
指着阅读技巧;右左法则
1. 从最里层的圆括号中未定义的标示符看起
2. 首先往右看,再往左看
3. 当遇到圆括号或者方括号时可以确定部分类型,
并调转方向
4. 重复2,3步骤,直到阅读结束
int (*p2)(int*, int (*f)(int*));p2是一个函数指针,指向一个返回值为int的函数,函数有两个参数一个是int*f,另一个参数是函数指针。
int (*p3[5])(int*);p3是一个5个元素的指针数组,每个元素是一个函数指针,即i指向函数int(int*)
int (*(*p4)[5])(int*);p4是数组数指针组指向有5个元素的数组,数组中存储函数指针,指向int(int*)的函数
int (*(*p5) (int*))[5]; p5是一个指针指向一个五个元素的指针数组,数组中每个元素指向函数int(int*)