c reference manual读书笔记(三)
这次主要是针对c语言中的声明(declaration)定义.
1 在c语言中声明的作用域(scope)可以分为4种,分别是 block/local scope, prototype scope, function scope以及file scope.其中file scope是最顶层的域. 如果一个声明不是external的,则默认这个声明就是被限制在它所出现的文件中.
2 一个标示符在它被完全声明之前是不能使用的。更精确的说就是从我们定义一个声明到这个声明的结束之间不能出现这个标示符.可是下面的例子是完全正确的,这是因为使用intsize(sizeof)之前,它已经被声明了:
1 |
|
而下面的例子则会编译出错,因为Test在使用之前还没有被声明.
1 |
|
3 c语言中也支持forward reference,不过只允许下面三种类型,分别是 在goto语句中的label,label都是在goto语句之后声明的;还有就是允许在struct,union,array类型的完全声明之前使用当前的声明,比如下面的例子
1 |
|
最后一种例外是函数的声明,这个原因是在c99之前,c语言允许隐式(implicitly)的声明,也就是如果一个函数在调用之前没有被声明,则在函数被调用的地方会隐式的声明这个函数(后面会详细介绍这个)。不过c99是不允许隐式的声明的.
4 c语言中允许5种类型的overload,overload是指相同名字的标示符。他们分别是 预处理器的宏名字,goto语句中的label,结构体/union/enum中的tag或者元素,最后剩下的归于一类.
5 之所以需要将overload分为5种类型,是为了更好的判断重复的声明。在c语言中如果相同的overloading类型中有2个或以上的相同名字的声明(在相同的block或者top-level(也就是file cope)),则将会报错 duplicate声明.比如下面的例子中howmany会报错,而str不会,这是因为str是属于同一个overloading class:
1 |
|
不过重复的声明也有例外,比如extern的声明,它可以出现任意多个.
6 c语言中的scope规则是,一个name的scope是开始于它定义的那个点,而不是它所被定义的block的开头,因此就会出现在相同的block的不同部分出现两个不冲突的定义同时被使用,比如下面的例子,将不会出错:
1 |
|
7 c语言中变量和函数都有生命周期,分为3种类型的生命周期,分别是static, local,以及dynamic.其中所有的函数都是static的.也就是程序启动时创建,退出时销毁.
8 c语言中静态变量默认会被初始化为0.而其他类型的变量,默认不会被初始化,初始值是没有定义的.并且静态变量只被初始化一次,哪怕包含这个静态变量的函数或者block被执行多次.
9 如果有多个extern修饰的声明,他们的类型是不兼容的,则结果是未定义的,不过在gcc中会直接报错.
10 c语言中有5种存储类修饰符(storage-class-specifier),分别是auto/extern/register/static/typedef.所有的top-level(file) scope默认都是extern的,除非你显式的制定存储类修饰符.而在block或者函数中的声明默认都是auto的.
11 c99之前函数的定义或者定义允许忽略返回值类型,默认为int,不过c99就不允许了.
1 |
|
static int k; //k为0
static int i = 0;
static int j = i; //错误
static float m;//m为0.0
static float n = m;//错误
static int *t;//t为NULL
static int *u = &k;//u为k的指针
1 |
|
int array[3] = {1, 2}; //array[2]将会是0
1 |
|
struct st {
int s;
};
static struct st s2 = {1};
static struct st s5 = s2;//出错
1 |
|
union un {
float s2;
int s;
};
union un2 {
int s;
float s2;
};
union un n= {1.1};//s2将会是1.1,而s是一个很大的整数.
union un2 n2 = {1.1};//s将会是1,而s2则是0
1 |
|
int x = 0;
```