首页 > 代码库 > 《C专家编程》笔记(三)——分析C语言的声明

《C专家编程》笔记(三)——分析C语言的声明

1. 几个C语言声明的分析

char (*j)[20];

j = (char(*)[20]) malloc(20); // j是指向数组的指针

const int * grape;

int const * grape;

int * const grape_jelly;

const int * const grape_jam;

int const * const grape_jam;

char * const * (*next)(); // next是指向函数的指针,这个函数不接收参数,它的返回值是指向char * const的指针。

 2. 一些非法声明及合法声明的限制条件

非法:函数的返回值不能是一个函数;函数的返回值不能是一个数组;数组里面不能有函数。

合法:函数的返回值允许是一个函数指针;函数的返回值允许是一个指向数组的指针;数组里面允许有函数指针;数组里面允许有其他数组。

 3. 声明的优先级规则

A. 声明从它的名字开始读取,然后按照优先级顺序依次读取。

B. 优先级从高到低依次是:

  B.1 声明中被括号括起来的那部分

  B.2 后缀操作符:

      括号( )表示这是一个函数,而

      方括号[]表示这是一个数组。

  B.3 前缀操作符:星号*表示“指向……的指针”。

C. 如果const和(或)volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符。在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

 4. 使用typedef来将声明简化

在ANSI C标准中,signal()的声明是void ( *signal( int sig, void( *func )( int ) ) ) ( int );

根据规则B.2,我们知道signal是个函数(这不同于上面的next,next是直接被括号括住),这个函数的参数是int sig, void(*func)(int),返回值是void (*)(int)。

我们使用typedef来提取signal声明中的通用部分,简化这个声明。

typedef void(*ptr_to_func) (int);

则signal的声明成了:ptr_to_func signal(int sig, ptr_to_func);

 5. typedef int x[10]和#define x int[10]的区别

typedef int x[10]将x设为含有10个元素的整型数组的类型。#define x int[10]只是简单地进行文本替换。

typedef int x[10];

x arr1, arr2, arr3; // 合法

#define x int[10];

x arr1, arr2, arr3; // 非法

#define peach int

unsigned peach i; // 合法

typedef int banana;

unsigned banana i; // 非法

#define int_ptr int *

int_ptr chalk, cheese; // chalk为int*, cheese为int

typedef int * int_ptr;

int_ptr chalk, cheese; // chalk和cheese均为int*

 6. 几条使用typedef的建议

不要为了方便起见对结构使用typedef。这样的唯一好处是可以节省书写struct,然而struct关键字可以向你提示这一信息。

typedef应该用在:数组、结构、指针以及函数的组合类型;可移植类型;为后面的强制类型转换提供一个简单的名字。

 

《C专家编程》笔记(三)——分析C语言的声明