跳到主要内容

declare

声明的语法

声明说明符 声明符;

存储类型限定符 符号限定符 类型说明符 声明符;
extern const int a[10];

说明说明符 描述声明的变量或函数的性质,分为:

  • 存储类型限定符:auto, static, extern, register
  • 符号限定符:const, volatile, restrict
  • 类型说明符:void, char, struct point ...
  • 函数说明符(C99):inline, 用来函数声明

存储类型

C语言中每个变量都具有3个性质:

  • 存储期限:决定为变量预留和内存被释放的时间。
    • 自动存储期:在所属块被执行时获得内存单元,并在块终止是释放内存单元;
    • 静态存储期:在程序运行期间占有同一个内存单元,在程序运行时一直保持内存占用;
  • 作用域:可用引用变量的那部分程序文本。(给编译器使用)
    • 块作用域:从声明的地方到所在块的末尾都是可见的;
    • 文件作用域:从声明的地方一直到所在的文件末尾都是可见的;
  • 链接:确定程序的不同部分可以共享此变量的范围。(给链接器使用)
    • 外部链接:变量可以被程序中的几个(或者全部)文件共享;
    • 内部链接:只能被一个文件中的任意函数共享;
    • 无链接: 属于单独的一个函数,不能被共享。

变量的默认存储期限、作用域和链接和声明的位置有关:

  • 在块(包括函数体)内部声明的变量具有自动存储期、块作用域,并且无链接;
  • 在程序的最外层声明的变量具有静态存储期、文件作用域和外部链接;
int i; //静态存储期限,文件作用域,外部链接

void f(void)
{
int j; //自动存储期限,块作用域,无链接
//每次都初始化
}
  • auto存储类型:只对属于块的变量有效。具有自动存储期限、块作用域,无链接。几乎不明确指定,块内变量默认就是这个;
  • static存储类型:就改变变量的存储期限,可能改变链接
static int i; //静态存储期限,文件作用域,内部链接

vaoid f(void)
{
int j; //静态存储期限,块作用域,无链接
//第一次才初始化
}
  • extern存储类型:使几个源文件可以共享同一个变量。变量可以在程序中声明多次,但只能有一次定义;
extern int i;
//静态存储期限;文件作用域;若早先被声明为static为内部链接,否则为外部链接

void f(void)
{
extern int j;
//静态存储期限;块作用域;若早先被声明为static为内部链接,否则为外部链接
}
  • register存储类型:要求编译器将变量放在寄存器中而不是内存。但是编译器会做出自己的选择。只对块内声明的变量有用,和auto变量有意义的存储类型。因为寄存器没有地址,所以对其做&运算是非法的。

函数的存储类型

函数的存储类型只有两个:

extern int f(int i);//外部链接,其他文件的函数可以调用
// ===> 等价于
int h(int i);

static int g(i);//内部链接,只能文件内部的还是可以调用

类型限定符

  • const:声明一些类似于变量的对象,但是对象是只读的
  • volatile

声明符

int i;          // 最简单的
int a[10]; // []
int *p; // *

初始化式

可以在声明的时候初始化值。

为初始化的变量:

  • 具有自动存储期限的变量没有默认的初始值,不能预测自动变量的初始值,而且每次变量变为有效时值可能不一样;
  • 具有静态存储期限的变量默认情况下值为零。整型为0,浮点为0.0,指针为NULL;

内联函数(C99)

在机器层面,调用函数组件可能需要先执行一些指令。调用本身需要跳转到函数的第一条质量,函数本身可能也需要执行一些额外的指令来启动执行,函数返回也需要一些工作。它们会拖慢程序。C89中带参数的宏解决这个问题,C99中可以通过创建内联函数来处理。

内联表明编译器把函数的每一次调用都用函数的机器指令来替代。编译文件可以更大,但是速度更快。具体实现看编译器(可能忽略)。

inline double average(double a, double b)
{
return (a+b) / 2;
}