ios appicon:C语言中的作用域和生命周期

来源:百度文库 编辑:偶看新闻 时间:2024/05/03 10:45:51
在C语言中,涉及到作用域和生存周期的问题,大多是指的变量和函数。         C语言中用得最多的应当算是局部变量了,而局部变量的作用域一般认为在函数体内有效。局部变量的内存分配管理和销毁是由编译器来实现的,程序编写者不用考虑其实现细节。当函数执行完成返回时,局部变量将全部被销毁,这决定了其生存周期。这里涉及到返回值的问题,至于是在返回值传递完成之后销毁呢,还是将返回值拷贝到一个临时变量中,销毁全部的局部变量,再将临时变量返回呢,这是由编译器的设计者所决定的。目前大多数的C编译器是采用的后者的设计方案。         刚刚提到局部变量的作用域一般认为是在函数体内。但是根据C99标准,该说法有了变化。在新的标准中,允许即时定义局部变量,示例如下:for( int i = 0; i < MAXSIZE; i++ ){….}例子中的局部变量i的作用域即在for循环的换括号中,当for循环结束的时候,局部变量i的生存周期同时结束。也就是说,在下一个for循环中,你仍然可以再次重新定义并使用名为i的局部变量。该语法只能在C99之后的新的C编译器中使用, 例如VC2005、VC2008、gcc4.2及以上版本。但是,该语法带来了编程风格的变化,而且变量隐含在了执行程序中,无论是代码的阅读和维护都有较大的困难,因此工程项目中不建议使用该语法。程序代码,是为了方便别人阅读而写的,而不是只有自己能够阅读。只有自己才能读得懂的代码,是没有使用价值的。函数退出时被销毁的局部变量包括整型、浮点型、数组、函数体中定义的指针(指针,对于编译器来说,它看到的依然是一个整型的变量而已)。    肯定有人会问到,如果想要函数体中的局部变量在函数退出时不被销毁,那该怎么办呢?其实这也简单,你只需要在定义的局部变量的前面加上static关键字,将其声明为静态变量即可。注意,静态变量的初始化只有一次,也就是当函数第一次被调用的时候将对静态变量进行初始化,之后类似于int i = 0这样的语句将会失效。一旦声明为静态变量,程序没有退出,静态变量将一直存在。使用静态变量的时候,一定要清楚为什么要使用静态变量,而不是仅仅为了某次操作,能够方便取得函数体中的某个变量的值而已。虽然其生存周期发生变化了,但是它的作用域依然限制在函数体的范围内。         把变量定义在函数体外,就是全局变量。全局变量的生命周期等同于程序执行时间,程序开始执行时,全局变量将被执行初始化(这与静态变量不同,静态变量是执行函数时才初始化的)。全局变量的优势就是,你可以在任何时候,任何函数中方便的访问到,实现数据共享。但同时,也存在共享数据被篡改的可能,尤其是多线程操作的时候,必须对每次操作进行加锁。在默认状态下,全局变量可以被工程项目中的任何文件和函数访问。但是,不同文件有所区别。如果是在定义全局变量的c文件中,无需声明就可以使用该变量;其他的c文件中,只需使用extern关键字进行声明(不是定义),即可使用。声明时,不能对全局变量进行赋值操作。全局变量一般不在h头文件中声明,容易发生重定义错误。extern int i ;           在C语言中,函数被默认为是全局的,只要在头文件中进行了声明,你可以在工程中的任何位置使用。在h头文件中,声明为int Foo(); 和extern int Foo(); 其实质是一样的。除此之外,你还可以将函数冠以static关键字,将其定义为静态函数。其意义在于,更改了函数的作用范围。声明为static的函数,只能在定义该函数体的c文件中使用,其他位置的程序段无法使用声明为static的函数。由于作用域的范围没有冲突,于是,你可以定义与声明为static同名的另一个函数,至于这个函数是全局的,还是静态的,无关紧要。因为在定义了同名的static函数的c文件中,编译器只会使用标记有static的函数,而忽略外部的全局函数。    很少讨论函数的生存周期,因为函数执行完成退出时,被认为其生命周期的结束。就算该函数再次被调用,那也是新的生存周期。另外,C语言中还有auto关键字,其实那更多的是编译器自己在用,而对于程序编写者来说,可以忽略掉。           大多数的书籍和文章对变量和函数的讨论也就到此结束了。而我想在这里谈论一下其他的几个方面: 宏定义         C语言中的宏定义是一个伟大的创新,也被称作是个愚蠢的设计。其实宏定义在程序的编译阶段就完成了,因此也就不存在生命周期这回事。通常宏定义出现在h头文件之中,也就是说只要你包含了这个头文件,你就可以用宏定义了;如果是定义在c文件之中的,那就只能在该c文件中使用了。 结构体         工程项目中,通常都是使用公共结构体来实现不同函数(或者功能模块)间的数据传递。公共结构体一般定义在外层的h头文件中。至于你要将其实例化为全局变量,还是局部变量,那需根据实际情况而定。 内存管理         前面提到的局部变量内存空间的申请销毁,是由编译器实现的。而使用malloc函数进行动态分配的内存空间,才需要使用free函数手动释放。关于内存分配管理很多中文书本都略过不谈,为什么呢?因为写书的人自己都没弄明白,结果给很多人带来困惑。         或许这本身确实很复杂,但却可以简单的解释下。原则上,一个程序能够使用的内存的范围是操作系统分配给程序的那部分。而这部分内存将随程序的退出而返还给操作系统。那么free执行的操作是什么呢?free函数释放的内存空间,实际上是释放给了程序本身,而不是操作系统。释放的空间可以再次分配给程序的其他函数体使用,而不需要再向操作系统申请,操作系统一般也不能够随便收回程序所正在使用的内存空间。(如果能够,那需要操作系统和编译器的双重支持才行,目前大多数操作系统都不支持。)程序使用free释放的内存空间,是程序的所有函数体所共享的。底层操作均由编译器实现,不需要程序编写者考虑。说简单点,malloc首先要求分配内存,若程序中剩余空间不能满足,就向操作系统要资源,用完了后不把这部分资源还给操作系统,直到程序的退出,操作系统才能对内存进行回收。这就是为什么程序占用内存始终是越来越多。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/leaf1984zh/archive/2010/10/25/5964256.aspx