C语言---存储类

文章目录

  • [1. auto (自动存储类)](#1. auto (自动存储类))
  • [2. register (寄存器存储类)](#2. register (寄存器存储类))
  • [3. static (静态存储类)](#3. static (静态存储类))
    • [A. 静态局部变量(Static Local Variables)](#A. 静态局部变量(Static Local Variables))
    • [B. 静态全局变量/函数(Static Global Variables/Functions)](#B. 静态全局变量/函数(Static Global Variables/Functions))
  • [4. extern (外部存储类)](#4. extern (外部存储类))

存储类是C语言中一个非常重要的概念,它用于规定变量/函数的作用域(Scope) 和生命周期(Lifetime)。
C语言中有四种主要的存储类说明符(Storage Class Specifiers):
1、auto
2、register
3、static
4、extern

1. auto (自动存储类)

关键字: auto

作用域: 局部(仅限于定义它的代码块内部,如函数内部、循环内部)。

生命周期: 自动的。当程序进入定义它的代码块时被创建,当退出该代码块时被自动销毁。每次进入代码块都会重新初始化(如果进行了初始化的话)。

存储位置: 内存的栈(Stack) 区。

注意: 所有局部变量默认的存储类,所以从不在代码中显式地写上 auto。auto 只能用在函数内,即 auto 只能修饰局部变量。

bash 复制代码
#include <stdio.h>

void myFunction() {
    auto int x = 10; // 等价于 int x = 10;
    printf("x = %d\n", x);
    x++;
}

int main() {
    myFunction(); // 输出:x = 10
    myFunction(); // 输出:x = 10 (每次调用都会重新创建和初始化x)
    return 0;
}

2. register (寄存器存储类)

关键字: register

存储位置: 建议编译器将变量存储在CPU的寄存器(Register) 中,而不是内存中,以期获得更快的访问速度。

重要限制: 量的最大尺寸等于寄存器的大小(通常是一个字),不能对 register 变量使用取地址运算符 &,因为寄存器没有内存地址。

注意: 这只是一个对编译器的建议(hint)。定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

c 复制代码
void calculate() {
    register int counter; // 建议编译器将counter放入寄存器
    for(counter = 0; counter < 10000; counter++) {
        // 频繁使用的循环变量是使用register的典型场景
    }
    // int *p = &counter; // 错误!不能获取register变量的地址
}

提醒:

不建议用于全局变量。

原因有以下两点:

a. 寄存器是稀缺资源

CPU中的寄存器数量非常有限(通常只有几十个),而且它们被系统用于各种关键操作。将一个全局变量长期占用一个寄存器是不现实且低效的,编译器几乎肯定会拒绝这个请求。

b. 取地址操作符 & 不可用

这是最直接的技术原因。register 关键字明确暗示该变量可能没有内存地址(因为它住在寄存器里)。因此,你不能对 register 变量使用取地址操作符 &。

3. static (静态存储类)

static 关键字用途很广,根据它修饰的是局部变量还是全局变量,含义有所不同。

A. 静态局部变量(Static Local Variables)

作用域: 局部(仍然仅限于定义它的代码块内部)。

生命周期: 静态的。它在程序整个运行期间都存在,不会随着函数调用结束而销毁。它只被初始化一次,下次函数调用时会保持上一次调用结束时的值。

存储位置: 内存的数据段(Data Segment) 或 BSS段。

bash 复制代码
#include <stdio.h>

void count() {
    static int c = 0; // 只初始化一次
    c++;
    printf("Count = %d\n", c);
}

int main() {
    count(); // 输出:Count = 1
    count(); // 输出:Count = 2 (保留了上一次的值)
    count(); // 输出:Count = 3
    return 0;
}

B. 静态全局变量/函数(Static Global Variables/Functions)

作用域: 文件作用域(File Scope)。被 static 修饰的全局变量或函数,其作用域被限制在定义它的源文件内部,不能被其他源文件通过 extern 引用。

目的: 用于实现封装和隔离,避免大型项目中多个源文件之间的命名冲突。

示例(两个文件):

bash 复制代码
static int private_var = 50; // 只能被file1.c中的函数访问

static void private_function() { // 只能被file1.c中的函数调用
    printf("This is private to file1.c\n");
}

void public_function() {
    private_function();
    printf("Accessing private_var: %d\n", private_var);
}
bash 复制代码
extern void public_function(); // 可以,声明在file1.c中定义的全局函数

// extern int private_var;      // 错误!无法链接到file1.c中的private_var
// void private_function();     // 错误!无法链接到file1.c中的private_function

int main() {
    public_function();
    return 0;
}

4. extern (外部存储类)

关键字: extern

用途: 用于声明一个在其他地方(通常是其他源文件)已经定义的全局变量或函数。它告诉编译器:"这个变量/函数存在,但定义在别处,你去链接的时候再找它的具体位置"。

作用域: 取决于它被声明的位置。如果是在函数内声明,则是块作用域;如果是在文件顶部声明,则是文件作用域。

生命周期: 整个程序运行期。

存储位置: 对于变量,位于数据段(Data Segment) 或 BSS段。

示例(两个文件):

global.h (头文件,可选)

bash 复制代码
extern int global_number; // 在头文件中声明外部变量
extern void display();    // 声明函数

file1.c (定义)

bash 复制代码
#include <stdio.h>
int global_number = 100; // 真正的定义,分配存储空间

void display() {
    printf("Global number is %d\n", global_number);
}

file2.c (使用)

bash 复制代码
#include <stdio.h>
// #include "global.h" // 也可以包含头文件,效果等同于下面两行
extern int global_number; // 声明,不分配存储空间,只是引用
extern void display();    // 声明

int main() {
    printf("%d\n", global_number); // 使用在file1.c中定义的变量
    display();                     // 调用在file1.c中定义的函数
    return 0;
}
相关推荐
XIAOYU6720132 小时前
金融数学专业需要学哪些数学和编程内容?
开发语言·matlab·金融
油炸自行车2 小时前
【Qt】编写Qt自定义Ui控件步骤
开发语言·c++·qt·ui·自定义ui控件·qt4 自定义ui控件
浪扼飞舟3 小时前
c#基础二(类和对象,构造器调用顺序、访问级别、重写和多态、抽象类和接口)
java·开发语言·c#
yuanpan3 小时前
python标准库有哪些模块,简单总结下。
开发语言·python
听情歌落俗3 小时前
MATLAB3-2数据存储-台大郭彦甫
开发语言·数学建模·matlab·矩阵
云天徽上3 小时前
【数据可视化-112】使用PyEcharts绘制TreeMap(矩形树图)完全指南及电商销售数据TreeMap绘制实战
开发语言·python·信息可视化·数据分析·pyecharts
NG WING YIN4 小时前
Golang關於信件的
开发语言·深度学习·golang
Sunny_yiyi4 小时前
Java根据模版导出PDF文件
java·开发语言·pdf
橘子134 小时前
C++实战:搜索引擎项目(二)
开发语言·c++·搜索引擎