不一样的C语言-auto,register,static,extern

auto,register,static,extern

《不一样的C语言》开篇中,笔者写出了对变量的认识,本篇文章中,笔者继续来探究与变量相关的auto,register,static,extern修饰符,进一步加深对变量的理解。

auto、register修饰的是变量,static和extern既能修饰变量也能修饰函数,本文中对于函数部分一笔带过,待研究函数时再来详细谈论。

一、auto修饰符:

auto,意为自动,修饰变量,称为自动变量。什么是自动变量?为何它是自动的?当我们在函数内部定义一个普通变量的时候(局部变量),它就是自动变量。你可能会疑惑,你只是简单的定义了一个变量并没什么用auto修饰。没错,当你在定义一个局部变量的时候,即使你不加,编译器都会默认帮你做这件事情。我们知道,普通局部变量的生命周期从变量被定义开始,到函数返回结束。我们不需要关心变量的存亡。自动变量在栈中分配,随着函数的进行被压入栈中,随着函数的结束被弹出栈外。这就是所谓的自动的含义。

二、register修饰符:

register,意外寄存器,修饰变量,称为寄存器变量。寄存器是存介质中最接近CPU也是速度最快的设备,将变量存储中这个介质中,无非就是想最大可能的提升变量的操作速度。对于现代编译器而言,register修饰符并不一定会“得逞”,register修饰符变成了对编译器的请求。求是求,编译器不一定满足你。这么做的原因我猜是编译器厂商认为编程的这帮人没有老程序员那么让人放心,于是乎对register进行了优化。对于register修饰的变量有这么几个要求:

1.register修饰的是局部变量。这很容易让人信服,因为寄存器虽快,但是数量非常有限。在一个庞大的计算机系统中,运行着许许多多你想运行和不想运行的程序,他们共享寄存器,如果以定义了大量的全局变量来占用寄存器,那寄存器资源就变得岌岌可危了,整个系统的速度不但没有提升反而下降。所以register修饰局部变量就显得顺理成章。

2.register不能用取地址符&。这不太让人好理解,事实上寄存器也是有内存地址的,但是为什么编译器不给我们取地址。我想这是出于安全的考虑。寄存器是一个极度共享的存储介质,寄存的意思就是短暂的停留,数据进进出出。程序与程序之间应该是相互隔离而不可见的,所以可能出于安全的考虑,编译器阻止了这个行为。

三、static修饰符:

static在C语言中,有两个意思,一个是本意:静态;另一个则是限定作用域。static修饰变量,恰有这两层意思。我们知道,变量分为局部变量和全局变量。
1.static修饰局部变量,让变量具有全局变量的某些属性。被static修饰的局部变量,其生命周期从被定义开始,到程序结束消亡,存储在数据区。静态局部变量只被初始化一次。虽然他的生命周期比普通的局部变量长了,但其作用域可见性并没有发生改变。也就是说我们只有进入函数内才能使用它。
2.static修饰全局变量,我们知道,全局变量的生命周期本身就是和程序共存亡。那么static修饰是否显得多余。这就引出了static的另一层含义:限定作用域。在全局变量前用static加以修饰,是告诉编译器,这个局部变量的作用域从被定义开始,到文件结束而结束,文件以外无法访问这个变量。对于static修饰的函数含义正是限定作用域,函数从被定义开始到文件结束的地方才能使用这个静态函数,外部不可访问。

四、extern修饰符:

extern意为外部,它同样可以修饰变量和函数。static修饰符把作用域定在了文件内部,而extern正好相反。它是告诉编译器,这个变量或者函数在其他文件中定义,当你编译的时候在文件中没有找到没关系,继续干你的活,链接的时候你自然能够找到。读者也看了关于extern的其他文章,讲的混乱而复杂,分了多种情况。在读者看来,对于extern的使用其实很简单,对于你自己写的变量和函数,如果你想被别人使用而不包含你的文件,只在链接的时候处理,那么你就加上extern。对于你使用别人的变量和函数,别管三七二十一,你加上不会错。

总结:

auto,register,static,extern都是修饰符,它们的存在无非就是为了补充说明它所修饰的对象的行为,相当于我们语言语法中的定语的作用,不管是什么修饰符,只要理解了其本质和注意事项就掌握好了。

下一篇文章:《不一样的C语言-const修饰变量》

你可能感兴趣的:(C语言深度剖析)