分析C语言的声明
在60年代晚期C语言的设计阶段,“类型模型(type model)”这个概念尚属陌生。
然后出现了一种C语言设计哲学,要求对象的声明形式与它使用的形式尽可能相似。
如果想要把什么东西的类型强制转换成指向数组的指针,就要这样:
char (*j)[20]; //j是一个指向数组的指针,数组内有20个char元素
j = (char (*)[20])malloc(20);
const int *grape; //指针所指向的对象是只读的
int const *grape; //同上
int * const grape_jelly; //指针是只读的,看来好象要把const放在*后面才能保证指针身只读
const int * const grape_jam; //两者都是只读的
int const * const grape_jam; //同上
声明是如何形成的
C语言中的声明:类型说明符 + 声明器 (+ 更多声明器) + 分号
类型说明符还包括存储类型和类型限定符。
类型说明符(type-specifier):
void char short int long signed unsigned float double
结构说明符(struct-specifier) struct
枚举说明符(enum-specifier) enum
联合说明符(union-specifier) union
存储类型(storage-class):
extern static register auto typedef
类型限定符(type-qualifier):
const volatile
声明器(declarator)是所有声明的核心。
它是标识符以及与它组合在一起的任何指针、函数括号、数组下标等。
指针可以是以下形式之一:
* const volatile
* volatile
*
* const
* volatile const
直接声明器可以是以下形式之一:
标识符
标识符[下标]
标识符(参数)
(声明器)
初始化内容(initializer)的形式为:
= 初始值
我们更关心代码是否容易阅读,而不是是否容易书写。
因此,变量的声明应该与类型的声明分开。
优先级规则
理解声明的优先级规则
A 声明从它的名字(最左边的标识符)开始读取,然后按照优先级顺序依次读取。
B 优先级从高到低依次是:
B.1 声明中被括号括起来的那部分
B.2 后缀操作符:
括号()表示这是一个函数,而
方括号[]表示这是一个数组。
B.3 前缀操作符:星号*表示“指向...的指针”。
C 如果const和(或)volatile关键字的后面紧跟着类型说明符(如int,long等),
那么它作用于类型说明符,在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。
例:char * const *(*next)()
next "next is "
* "pointer to "
() "function returning "
* "pointer to "
const "read-only "
* "pointer to "
char "char "
例:char *(* c[10])(int **p)
c "c is "
[10] "array 0..9 of "
* "pointer to "
(int **p) "function returning "
* "pointer to "
char "char "
typedef int x[10]和#define x int[10]的区别
可以用其他类型说明符对宏类型名进行扩展,
但是,若使用typedef声明它之后,就不能再往里面增加别的东西。
在连续几个变量的声明中,用typedef定义的类型能够保证所有的变量均为同一种类型,如:
typedef char * char_ptr;
char_ptr Bentley, Rolls_Royce;
typedef struct foo{...foo;}的含义
typedef struct [结构标签]
{
类型1 标识符1;
...
类型N 标识符N;
}结构类型 [变量定义];
struct 结构类型
{
类型1 标识符1;
...
类型N 标识符N;
}[变量定义];
结构类型 变量定义;
应该始终在结构定义中使用结构标签。
source: 《Expert C Programming》
如果想要把什么东西的类型强制转换成指向数组的指针,就要这样:
char (*j)[20]; //j是一个指向数组的指针,数组内有20个char元素
j = (char (*)[20])malloc(20);
const int *grape; //指针所指向的对象是只读的
int const *grape; //同上
int * const grape_jelly; //指针是只读的,看来好象要把const放在*后面才能保证指针身只读
const int * const grape_jam; //两者都是只读的
int const * const grape_jam; //同上
声明是如何形成的
C语言中的声明:类型说明符 + 声明器 (+ 更多声明器) + 分号
类型说明符还包括存储类型和类型限定符。
类型说明符(type-specifier):
void char short int long signed unsigned float double
结构说明符(struct-specifier) struct
枚举说明符(enum-specifier) enum
联合说明符(union-specifier) union
存储类型(storage-class):
extern static register auto typedef
类型限定符(type-qualifier):
const volatile
声明器(declarator)是所有声明的核心。
它是标识符以及与它组合在一起的任何指针、函数括号、数组下标等。
指针可以是以下形式之一:
* const volatile
* volatile
*
* const
* volatile const
直接声明器可以是以下形式之一:
标识符
标识符[下标]
标识符(参数)
(声明器)
初始化内容(initializer)的形式为:
= 初始值
我们更关心代码是否容易阅读,而不是是否容易书写。
因此,变量的声明应该与类型的声明分开。
优先级规则
理解声明的优先级规则
A 声明从它的名字(最左边的标识符)开始读取,然后按照优先级顺序依次读取。
B 优先级从高到低依次是:
B.1 声明中被括号括起来的那部分
B.2 后缀操作符:
括号()表示这是一个函数,而
方括号[]表示这是一个数组。
B.3 前缀操作符:星号*表示“指向...的指针”。
C 如果const和(或)volatile关键字的后面紧跟着类型说明符(如int,long等),
那么它作用于类型说明符,在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。
例:char * const *(*next)()
next "next is "
* "pointer to "
() "function returning "
* "pointer to "
const "read-only "
* "pointer to "
char "char "
例:char *(* c[10])(int **p)
c "c is "
[10] "array 0..9 of "
* "pointer to "
(int **p) "function returning "
* "pointer to "
char "char "
typedef int x[10]和#define x int[10]的区别
可以用其他类型说明符对宏类型名进行扩展,
但是,若使用typedef声明它之后,就不能再往里面增加别的东西。
在连续几个变量的声明中,用typedef定义的类型能够保证所有的变量均为同一种类型,如:
typedef char * char_ptr;
char_ptr Bentley, Rolls_Royce;
typedef struct foo{...foo;}的含义
typedef struct [结构标签]
{
类型1 标识符1;
...
类型N 标识符N;
}结构类型 [变量定义];
struct 结构类型
{
类型1 标识符1;
...
类型N 标识符N;
}[变量定义];
结构类型 变量定义;
应该始终在结构定义中使用结构标签。
source: 《Expert C Programming》