1、类型修饰符
类型修饰符必须放在它所修饰的类型名之前。
1.1、const
const型变量不能被程序修改,然而能被赋予初始值。编译程序把这类变量放入只读区。
eg:
const int a=10;//a值在以后被使用中都不能被改变
const 修饰符可以保护函数的参数指针指向的对象,使之免受函数修改。向一个函数传入指针时,该函数可以改变该指针指向的对象,在函数形参的声明中把指针定义为const型时,函数代码无法修改指针指向的实际变量,示例如下:
void func(const char *str)
{
while(*str)
{
if(*str == ' ') printf("%c",'-');
else printf("%c",*str);
str++;
}
}
如果改成如下形式,编译器会报错
void func(const char *str)
{
while(*str)
{
if(*str == ' ') *str = '-';//can't do this;str is const
<span style="white-space:pre"> </span>printf("%c",*str);
str++;
}
}
程序中,也可以用const确保变量不受任何程序修改。const型变量可以由程序外的成分修改,例如,硬件设备可以改变const型变量的值。无论如何,只要声明成const,它的内容只随外部事件变化。如DMA的使用,可以将DMA指向的内存空间设为const,程序不可以改变,但DMA可以(只是猜想,未实践)。
1.2、volatile
修饰符volatile把一个事实告诉编译器,说明变量的值可能未在程序中明确表达的方法改变。例如,把全局变量的地址传入操作系统的时钟子程序,用该全局变量保存系统的实时时钟值。此时虽然程序中没有直接书写赋值语句,但变量的内容却是变化了。这种修饰十分重要,原因在于系统的自动优化操作多数编译程序在变量不出现在赋值语句左侧时认为变量的值不变,从而自动优化某些表达式,使每次使用该变量时不再重查其值。某些编译程序优化过程还改变变量在表达式的顺序。修饰符volatile防止这类优化中的改变。
const可以和volatile同时使用。如,0x30定义为一个端口值,只受外部条件的修改,则以下声明将消除任何偶然的副作用
const volatile char *port = (const volatile char *)0x30;
2、存储类型说明符
C语言支持4种存储类型说明符:extern static register auto
这些说明符告诉编译器应该怎样保存有关变量,一般形式为
storage specifier type var name;
2.1、extern
C定义了三类外部链接:外部链接、内部链接、和无链接。通常函数和全局变量具有外部链接。
extern的主要作用说明在程序的其他地方用外部链接声明的对象。声明表述对象的名称和类型,定义则导致为对象分配存储空间。同一对象可以有许多声明,但定义只有一个。
很多情况下,变量的声明也是定义。但是,在变量名之前加上extern说明符,可以声明变量而不定义它。这样,当需要引用在程序的其他地方定义的变量是,则可以用extern声明该变量。
注意如果将变量初始化,那么extern声明将变成定义,如:
extern int a=3;
在实际使用中,一般定义放在某个C文件中,然后extern声明包含在H文件中,每个源代码文件包含该H文件。
2.2、static
定义为static的变量是函数或文件中的永久变量。函数外或文件外看不到静态变量,函数调用之间,静态变量保持其值。
static局部变量
int series(void)
{
static int number = 100;
return number--;
}
首次进入代码块时,给局部静态变量赋初值,以后进入不在赋初值,而是保持上一次计算结果。
static全局变量
static全局变量值在其驻留的文件认可,对外部文件充分隐蔽,外部程序若想访问该变量,可以通过函数访问如:
static int number;
int get_number(void)
{
return number;
}
void set_number(int dat)
{
number = dat;
}
2.3 register变量
这种存储类型用于使用次数很多的变量,需要程序尽快访问该变量,一般是把变量存放在CPU寄存器中,具体由编译器和环境决定。
register只能施用于局部变量和函数形参,因此全局(register)变量是非法的。
计算m的e此幂:
int int_per(register int m,register int e)
{
register int temp;
temp = 1;
for(;e;e--)temp=temp*m;
return temp;
}
注意在C语言中,不能用&操作符获得register变量地址,因为register变量可以放在CPU寄存器中,该寄存器是不编址的。
在实践中,register一般只对整形和字符型有实际作用。