如何优雅的解析C语言声明系统

可以先阅读《巧解函数指针的声明》热热身,理论上,《C专家编程》中的方法可以分析所有C复杂声明,非常科学。

历史原因

  • 19世纪60年代晚期,人们在设计C语言这部分内容的时候,“类型模型”这个概念对于当时的编程语言理论而言尚属于陌生。
  • BCPL语言(C的祖先)甚至没有类型,只有二进制字作为唯一的数据类型,所以C先天不足
  • C语言的设计哲学,要求对象的声明形式和它的使用形式尽可能的相似
  • 最大的问题是无法从左到右依次阅读一个声明
char (*j)[20];
j = (char(*)[20]) malloc(20);
char* const*(*next)();

声明器与声明

  • 主要涉及三个符号,指针*,数组[],函数(),优先级后两者大于前者
    • 函数的返回值不能是一个函数,foo()()非法
    • 函数的返回值不能是一个数组,foo()[ ]非法
    • 数组里面不能有函数,foo[ ]()非法
    • 函数的返回值可以是函数指针,int (*func())();返回值是int(*)()
    • 函数的返回值可以是指向数组的指针,int(*foo())[ ];返回值是int(*)[ ]
    • 数组里面可以有函数指针,int(*foo[ ])();数组里是int(*)()
    • 数组里可以有其他数组,int foo[ ][ ]
  • 上面三条总结起来就是[]和()不能同时出现,但是可以和*一起出现

enter image description here
enter image description here

优先级规则

enter image description here

enter image description here

enter image description here

typedef

  • typedef为一种类型引入一个新的名字,而不是为变量分配内存空间
  • 不要在1个typedef后面放入太多声明,不要把typedef放在声明的中间部分,如下所示
typedef int \*ptr, (*fuc)(), arr[5];
unsigned const long typedef int volatile *kumquat;
  • 一般情况下,typedef用于简洁的表示指向其他东西的指针,如下所示
//signal函数两个参数,1个int,1个函数指针void(*)(int)
//void(*)(int)是用户自定义的信号处理函数
//返回值也是1个函数指针void(*)(int)
void (*signal(int,void(*)(int)))(int);
typedef void (*HANDLER) (int);
HANDLER signal(int, HANDLER);
  • typedef类似宏文本替换,因为它不引入新类型,但是typedef声明之后不能在修改内部的封装,在几次连续的声明中,typedef可以保证每个都正确,宏不能保证;
#define x int[10]
typedef int x[10];

#define peach int
unsigned peach i;//合法
typedef banana int;
unsigned banana j;//不合法

typedef struct foo{int foo;} foo;的含义

C语言存在很多名字空间:

  • 标签名:
  • 标签:用于所有的结构,枚举,联合
  • 成员名:每个结构或联合都有自身的名字空间
  • 其他

在同一个名字空间内部,任何名字都必须具有唯一性,但在不同的空间中,可以存在相同的名字。因为每个结构或联合都有自己的名字空间,它们可以有相同的成员名字。

  • 不要为省写struct而用typedef
  • 应该在数组,结构,指针以及函数的复合类型中使用
  • 使用_tag

Reference

C专家编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值