C笔记:指针数组 数组指针 指针函数 函数指针

C语言中的重点

1:用变量a给出下面的定义:一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数并返回一个整型数

正确答案:int (*a[10])(int);

int *a[10]; //指向int类型的指针数组a[10]

int (*a)[10]; //指向有10个int类型数组的指针a

int (*a)(int);//函数指针,指向有一个参数并且返回类型 均为int的函数

int (*a[10])(int); //函数指针的数组,指向有一个参数并且返回类型均为int的函数的数组

int *a[10]; //指向int类型的指针数组a[10]

int (*a)[10]; //指向有10个int类型数组的指针a

int (*a)(int);//函数指针,指向有一个参数并且返回类型 均为int的函数

int (*a[10])(int); //函数指针的数组,指向有一个参数并且返回类型均为int的函数的数组

int*p[4];         // 指针数组。  是个有4个元素的数组,每个元素的是指向整型的指针。 ( 数组的每个元素都是指针 )

int(*p)[4];       // 数组指针。  它是一个指针,指向有4个整型元素的数组。  ( 一个指针指向有 4 个整型元素的数组 )

  int*func(void);   // 指针函数。 无参函数,返回整型指针。            ( 函数的返回值为 int* ) 

int(*func)(void); // 函数指针,可以指向无参,且返回值为整型指针的函数。            ( 函数的返回值为 int )

右左法则:首先从最里面的圆括号(未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明。

从未定义的标识符开始阅读,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个

现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:

 

int(*func)(int*p);

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个 号,这说明 func 是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明 (*func是一个函数,而 func 是一个指向这类函数的指针,就是一个函数指针,这类函数具有 int类型的形参,返回值类型是 int。

int(*func)(int*p,int(*f)(int*));

func 被一对括号包含,且左边有一个 号,说明 func 是一个指针,跳出括号,右边也有个括号,那么 func 是一个指向函数的指针,这类函数具有 int和int(*)(int*) 这样的形参,返回值为 int 类型。再来看一看 func 的形参 int(*f)(int*),类似前面的解释,f 也是一个函数指针,指向的函数具有 int类型的形参,返回值为 int。

int(*func[5])(int*p);

func 右边是一个 [] 运算符,说明 func 是一个具有 5 个元素的数组,func 的左边有一个 *,说明 func 的元素是指针,要注意这里的 不是修饰 func的,而是修饰 func[5的,原因是 [] 运算符优先级比 高,func先跟 [] 结合,因此 修饰的是 func[5]。跳出这个括号,看右边,也是一对圆括号,说明 func 数组的元素是函数类型的指针,它所指向的函数具有 int类型的形参,返回值类型为 int。

int(*(*func)[5])(int*p);

func 被一个圆括号包含,左边又有一个 *,那么 func 是一个指针,跳出括号,右边是一个 [] 运算符号,说明 func 是一个指向数组的指针,现在往左看,左边有一个 号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func 是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有 int形参,返回值为 int 类型的函数。

int(*(*func)(int*p))[5];

func 是一个函数指针,这类函数具有 int类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int 元素的数组。

要注意有些复杂指针声明是非法的例如

int func(void)[5];

func 是一个返回值为具有 5 个 int 元素的数组的函数。但 C 语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C/C++ 语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。

int func[5](void);

func 是一个具有 5 个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。

实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用 typedef 来对声明逐层分解,增强可读性,例如对于声明:

int(*(*func)(int*p))[5];

可以这样分解:

typedef int(*PARA)[5];

typedef PARA(*func)(int*);

这样就容易看得多了。

int(*(*func)[5][6])[7][8];

func 是一个指向数组的指针,这类数组的元素是一个具有 5×6 个 int 元素的二维数组,而这个二维数组的元素又是一个二维数组。 

如下,typedef 的分解方法:

typedef int(*PARA)[7][8];

typedef PARA(*func)[5][6];

int(*(*(*func)(int*))[5])(int*);

func 是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int形参,返回值为int。

typedefint(*PARA1)(int*);

typedef PARA1(*PARA2)[5];

typedef PARA2(*func)(int*);

int(*(*func[7][8][9])(int*))[5];

func 是一个数组,这个数组的元素是函数指针,这类函数具有 int的形参,返回值是指向数组的指针,所指向的数组的元素是具有 5 个int 元素的数组。

typedefint(*PARA1)[5];

typedef PARA1(*PARA2)(int*);

typedef PARA2 func[7][8][9];

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值