学而时习之: C语言的变量

90 阅读7分钟

C 语言中的变量

C 语言中的变量是一块“有名内存”,用来保存数据,并在需要时通过名字随时访问。它让我们不必记住确切的内存地址就能使用内存。

创建变量时,必须同时给出“数据类型”和“名字”,语法如下:

数据类型 名字;

C 提供了多种数据类型,几乎可以存储所有常见数据,例如:int、char、float、double 等。

示例:

int num;        // 整数
char letter;    // 字符
float decimal;  // 单精度浮点数

在 C 中,所有变量必须“先声明、后使用”。同一类型的多个变量可在一条语句中声明,用逗号分隔:

数据类型 名字1, 名字2, 名字3, ...;

C 变量命名规则
只要满足以下条件,可任意取名:

  1. 只能由字母、数字和下划线组成。
  2. 必须以字母或下划线开头,不能以数字开头。
  3. 不能出现空白字符。
  4. 不得使用保留字(关键字)。
  5. 同一作用域内名字必须唯一。

C 语言变量的初始化

变量声明后,需要把第一个有用的值存进去,这个值叫“初值”,这个过程叫“初始化”。用赋值运算符 = 完成。

int num;   // 先声明
num = 3;   // 再初始化

注意:变量刚声明时里面只是“垃圾值”(随机数据),所以初始化很重要。也可以“声明 + 初始化”一步完成:

int num = 3;

提示:赋给变量的值必须与声明时的类型一致,否则出错。

访问变量
想使用变量里保存的数据,直接写变量名即可。

示例:

#include <stdio.h>

int main() {
    int num = 3;        // 创建并初始化
    printf("%d", num);  // 通过名字访问,输出 3
    return 0;
}

修改变量中的值

在程序运行过程中,可以随时用赋值运算符 = 把一个新值重新放进变量。

示例:

#include <stdio.h>

int main() {
    int n = 3;   // 创建并初始化为 3
    n = 22;      // 把新值 22 存进去,旧值 3 被覆盖
    printf("%d", n);  // 输出 22
    return 0;
}

如何在 C 中使用变量

变量就是内存地址的“名字”,里面装着某个值。只要语法上允许使用“值”的地方,就可以用变量名代替——变量名就是它所存值的替身。

示例:整数变量可以直接写在数学表达式里,代替具体的数字。

#include <stdio.h>

int main() {
    // 直接用字面值计算
    int sum1 = 20 + 40;

    // 先定义变量
    int a = 20, b = 40;

    // 用变量代替字面值计算
    int sum2 = a + b;

    printf("%d\n%d", sum1, sum2);  // 两行结果都是 60
    return 0;
}

C 变量的内存分配

在“声明”阶段,编译器只知道某个名字和类型存在,此时并未真正分配内存;只有当变量被“定义”时,编译器才会为它划出一块具体内存。
在 C 语言里,通常把“声明 + 定义”合并成一条语句完成(例如前面所有例子)。
分配给变量的字节数由它的类型决定,可用 sizeof 运算符查看。
示例:

#include <stdio.h>

int main() {
    int num = 22;

    // 查看 num 占多少字节
    printf("%zu bytes", sizeof(num));  // 常见输出:4 bytes
    return 0;
}

变量根据存储类别的不同,也会被放到内存的不同区域。

C 语言中的存储类别

存储类别用于规定变量的生命周期作用域可见性。它决定了变量存放在哪里、值会保留多久、以及能被谁访问,从而帮助我们在程序运行期间追踪某一变量的“存在轨迹”。C 语言共有 4 种主要存储类别:

  • auto
  • register
  • static
  • extern

auto(自动)

函数或代码块内部声明的变量,默认就是 auto 类型。这类变量只能在所属代码块/函数内使用,离开该范围就不可见。

auto 变量特性

  • 作用域:局部
  • 默认值:垃圾值(随机)
  • 内存位置:RAM
  • 生命周期:到所属作用域结束为止
    解释:
  • auto 关键字用于显式声明一个“自动存储期”的局部变量。
  • 但在 C 语言里,局部变量默认就是 auto,写不写都一样,因此通常省略。
  • 函数前不能加 auto,因为函数本身并不受块作用域限制。 示例:
#include <stdio.h>
int main() {
    auto int x = 10;  // auto 可省略,这是默认行为
    printf("%d", x);
    return 0;
}

static(静态)

该存储类别用来声明“静态变量”,其特点是:即使离开作用域,变量值仍然被保留。因此,下次再进入作用域时,能继续使用上一次留下的值。

static 存储类特性

  • 作用域:局部(只能在本代码块/函数内按名访问)
  • 默认值:0(未显式初始化时自动清零)
  • 内存位置:RAM
  • 生命周期:贯穿整个程序运行期间

示例:

#include <stdio.h>
void counter() {
    static int count = 0;  // 静态变量,只初始化一次
    count++;
    printf("Count = %d\n", count);
}
int main() {
    counter();  // 输出 Count = 1
    counter();  // 输出 Count = 2
    return 0;
}

解释: 变量 count 在第一次调用时创建并初始化为 0,函数结束后值仍被保留;第二次调用时不再重新初始化,而是继续在上一次的基础上累加,因此输出 2。

register(寄存器)

该存储类别用于声明“寄存器变量”。它的功能与 auto 变量完全一样,唯一的区别是:编译器会尽量把这类变量放进 CPU 的寄存器里(如果有空闲寄存器),从而让访问速度远高于普通内存变量。

register 存储类特性

  • 作用域:局部
  • 默认值:垃圾值(随机)
  • 内存位置:优先 CPU 寄存器,否则退回到 RAM
  • 生命周期:到所属作用域结束为止

注意:编译器可能因寄存器不足而忽略你的“建议”。

示例:

#include <stdio.h>
int main() {
    register int i;  // 建议把 i 放进寄存器
    for (i = 0; i < 5; i++) {
        printf("%d ", i);
    }
    return 0;
}

解释: register 只是一个“提示”。如果编译器觉得可行,就会把 i 放入寄存器以加快循环速度;若寄存器不够用,它会像普通 auto 变量一样处理。

extern(外部)

extern 存储类用来告诉编译器:“这个变量是在别的代码块(或别的源文件)里真正定义的,此处只是声明,并不分配内存”。 因此,它的值可以在别的块里赋值或修改

extern 存储类特性

  • 作用域:全局(整个程序都能按名访问)
  • 默认值:0(未显式初始化时自动清零)
  • 内存位置:RAM
  • 生命周期:程序结束才释放

示例:
文件 printVar.c

/* 仅声明,不定义 */
extern int globalVar;   // 告诉编译器:真正的定义在别处

文件 main.c

#include <stdio.h>
int globalVar = 100;    // 真正的定义 + 初始化
void printGlobalVar();  // 函数原型
int main() {
    printGlobalVar();   // 输出:Global variable is: 100
    return 0;
}

编译方法(GCC 需要把两个文件一起编译):

gcc main.c printVar.c -o main

总结:在 C 语言中,存储类别定义了变量的生存期、作用域和可见性。它们规定了变量在运行内存中的存储位置、值的保留时间以及访问方式,这些特性帮助我们在程序运行期间追踪特定变量的存在。

存储说明符存储位置初始值作用域生命周期
auto垃圾值代码块内部代码块结束
extern数据段全局,多文件程序结束为止
static数据段代码块内部程序结束为止
registerCPU 寄存器垃圾值代码块内部代码块结束

你会发现上面的示例都是搞得在方法内部声明的局部变量, 普通全局变量放在“数据段”(Data Segment),程序一加载就存在,直到进程结束才释放。记住全局变量不能用auto,register来修饰噢!!! image.png

C 语言中变量的作用域

前面说“变量一旦声明就能在任何地方使用”,其实只讲对了一半。变量只能在它的作用域——即名字有效的程序区域——中被访问。作用域通常就是一对花括号 {} 所包围的区域。

示例:

// 这里不能访问 num

int main() {
    // 这里也不能访问 num
    {
        int num;  // 变量声明
    }             // 作用域结束
    // 这里依旧不能访问 num
    return 0;
}

C 语言中的常量

如果希望变量的值不允许被修改,可以用 const 关键字把它定义成常量

语法:

const 数据类型 名字 = 值;

常量必须在声明时就初始化,否则编译报错。