《C Primer Plus》第12章 存储类、链接和内存管理

12.1.6 具有代码块作用域的静态变量

静态变量(static variable)听起来⾃相⽭盾,像是⼀个不可变的变
量。实际上,静态的意思是该变量在内存中原地不动,并不是说它的
值不变。具有⽂件作⽤域的变量⾃动具有(也必须是)静态存储期。
前⾯提到过,可以创建具有静态存储期、块作⽤域的局部变量。这些
变量和⾃动变量⼀样,具有相同的作⽤域,但是程序离开它们所在的
函数后,这些变量不会消失。也就是说,这种变量具有块作⽤域、⽆
链接,但是具有静态存储期。计算机在多次函数调⽤之间会记录它们
的值。在块中(提供块作⽤域和⽆链接)以存储类别说明符static(提
供静态存储期)声明这种变量

复制代码
/*loc_stat.c --使用局部静态变量*/
#include <stdio.h>
void trystat(void);
 
int main(void)
{
    int count;
    
    for(count = 1; count <=3; count++)
    {
        printf("Here comes iteration %d:\n",count);
        trystat();
    }
    return 0;
}
void trystat(void)
{
     int fade = 1;
     static int stay = 1;
     
     printf("fade = %d and stay = %d\n",fade++,stay++);
复制代码

静态变量stay保存了它被递增1后的值,但是fade变量第次都是1.这表明了初始化的不同。每次调用trystat()都会初始化fade,但是stay只在编译trystat()时被初始化一次。如果未显式初始化静态变量,它们会初始化为0。

下面两个声明很相似:

int fade = 1;

static int stay = 1;

第1条声明 确实是trystat()函数的一部分,每次调用该函数时都会执行这条声明。这是运行时的行为

第2条声明实际上并不是trystat()函数的一部分。如果逐步调度该程序会发现。程序似乎跳过了这条声明。这是因为静态变量和外部变量在程序被入内存忆执行完毕。把这条声明放在trystat()函数中是为了告诉编译顺只有trystat()函数才能看到该变量。这条声明并未在运行是执行。

 

12.1.7 具有外部链接的静态变量

外部变量初始化:

int x2 = 2 * x  //不可以,x是一个变量 

 

假设这样写:
extern int tern;
int main(void)
{
编译器会假设 tern 实际的定义在该程序的别处,也许在别的⽂件
中。该声明并不会引起分配存储空间。因此,不要⽤关键字extern创建
外部定义,只⽤它来引⽤现有的外部定义。

外部变量只能初始化⼀次,且必须在定义该变量时进⾏。假设有
下⾯的代码:

// file_one.c
char permis = 'N';
...

// file_two.c
extern char permis = 'Y'; /* 错误 */
file_two中的声明是错误的,因为file_one.c中的定义式声明已经创
建并初始化了permis。

 

12.1.9 多文件

只有当程序由多个翻译单元组成时,才体现区别内部链接和外部链接的重要性。接下来简要介绍一下。

复杂的C程序通常由多个单独的源代码文件组成。有时,这些文件可能要共享一个外部变量。C通过在一个文件中进行定义式声明,然后在其他文件中进行引用式声明来实现共享。也就是说,除了一个定义式声明外,其他声明都要使用extern关键字。而且,只有定义式声明才能初始化变量。

注意,如果外部变量定义在一个文件中,那么其他文件在使用该变量之前必须先声明它(用 extern关键字)。也就是说,在某文件中对外部变量进行定义式声明只是单方面允许其他文件使用该变量,其他文件在用extern声明之前不能直接使用它。

12.10

用 static 说明符创建的对象具有静态存储期,载入程序时创建对象,当程序结束时对象消失。如果static 用于文件作用域声明,作用域受限于该文件。如果 static 用于块作用域声明,作用域则受限于该块。因此,只要程序在运行对象就存在并保留其值,但是只有在执行块内的代码时,才能通过标识符访问。块作用域的静态变量无链接。文件作用域的静态变量具有内部链接

 

posted @   清风oo  阅读(70)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2018-03-28 位、字节和字
点击右上角即可分享
微信分享提示