C语言变量与常量

在程序中,数据需要被存储和操作。C语言提供了变量常量两种机制来管理数据。 变量是可以在程序运行过程中改变值的存储单元,而常量则是固定不变的值。 理解它们的区别与用法是编写灵活、可靠程序的关键。

📦 变量

变量本质上是一块内存区域的名称,用于存储特定类型的数据。通过变量名,我们可以访问或修改这块内存中的值。

🔹 变量的声明与定义

在C语言中,变量需要先声明(指定类型和名称)后才能使用。声明同时也可以定义(分配内存)。 语法:数据类型 变量名;数据类型 变量名 = 初始值;

int age;              // 声明并定义一个整型变量 age(未初始化)
float price = 99.9;   // 定义并初始化为 99.9
char grade = 'A';     // 定义字符变量并初始化
最佳实践: 建议在定义变量时就进行初始化,避免使用未初始化的变量(其值是不确定的)。

🔹 变量命名规则

  • 只能包含字母、数字和下划线 _
  • 不能以数字开头。
  • 不能使用C语言的关键字(如 intreturnif 等)。
  • 区分大小写(scoreScore 是不同的变量)。
  • 建议使用有意义的名称(如 student_age 而不是 a)。

🔹 变量的作用域

作用域决定了变量在程序的哪些部分可以被访问。C语言主要有以下几种作用域:

  • 块作用域:在 {} 内定义的变量,只在该代码块内有效。
  • 函数作用域:在函数内部定义的变量(局部变量)只在该函数内有效。
  • 文件作用域:在所有函数之外定义的变量(全局变量)在整个文件中有效,甚至可以通过 extern 扩展到其他文件。
#include <stdio.h>

int globalVar = 100;   // 全局变量,文件作用域

void func() {
    int localVar = 10;  // 局部变量,函数作用域
    printf("局部变量: %d\n", localVar);
    printf("全局变量: %d\n", globalVar);
}

int main() {
    if (1) {
        int blockVar = 20;  // 块作用域,仅在if语句块内有效
        printf("块变量: %d\n", blockVar);
    }
    // printf("%d", blockVar); // 错误!blockVar在此处不可见
    func();
    return 0;
}

🔹 变量的存储类别

C语言提供了四种存储类别说明符,用于控制变量的生命周期和作用域:

存储类别关键字作用域生命周期初始值
自动变量auto(默认)块作用域函数调用时创建,结束时销毁未初始化时为垃圾值
寄存器变量register块作用域与自动变量类似,建议存入CPU寄存器未初始化时为垃圾值
静态局部变量static块作用域程序整个运行期间默认初始化为0
外部变量extern文件作用域(可跨文件)程序整个运行期间默认初始化为0
#include <stdio.h>

void counter() {
    static int count = 0;  // 静态局部变量,只初始化一次
    count++;
    printf("调用次数: %d\n", count);
}

int main() {
    counter();  // 输出1
    counter();  // 输出2
    counter();  // 输出3
    return 0;
}

🔒 常量

常量是在程序执行期间值不会改变的量。C语言中有多种定义常量的方式:

🔹 字面常量

直接写在代码中的固定值,如 103.14'A'"Hello"

int a = 100;        // 100 是整型字面常量
float pi = 3.14159; // 3.14159 是浮点型字面常量
char ch = 'M';      // 'M' 是字符型字面常量

🔹 使用 #define 定义符号常量(宏常量)

预处理指令,在编译前进行文本替换,没有类型检查。

#define PI 3.14159
#define MAX_STUDENTS 100

int main() {
    double area = PI * 10 * 10;
    int students[MAX_STUDENTS];
    return 0;
}

🔹 使用 const 关键字定义常量

const 修饰的变量具有类型,编译时会进行类型检查,更安全。

const double PI = 3.14159;
const int MAX = 100;

int main() {
    // PI = 3.14;   // 错误!不能修改 const 变量的值
    printf("PI = %f\n", PI);
    return 0;
}
#define vs const:
  • #define 是预处理阶段替换,不占内存,无类型;const 是运行时变量,有类型,可调试。
  • 建议在C语言中,对于真正的常量(如数学常数、数组大小)使用 #defineconst 均可,但 const 更符合现代编程风格。

🔹 枚举常量

使用 enum 定义一组相关的整数常量,增强代码可读性。

enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN };
enum Color { RED = 1, GREEN = 2, BLUE = 4 };

int main() {
    enum Weekday today = MON;
    printf("today = %d\n", today);   // 输出 0
    return 0;
}

📝 综合示例:变量与常量实战

#include <stdio.h>

#define TAX_RATE 0.06      // 宏常量

const double DISCOUNT = 0.8;  // const常量

int main() {
    // 变量定义
    double price = 99.9;
    int quantity = 3;
    static int totalSold = 0;  // 静态变量,记录总销量

    double subtotal = price * quantity;
    double tax = subtotal * TAX_RATE;
    double finalPrice = subtotal + tax;

    // 应用折扣(如果满足条件)
    if (quantity >= 5) {
        finalPrice *= DISCOUNT;
    }

    totalSold += quantity;

    printf("商品单价: %.2f\n", price);
    printf("购买数量: %d\n", quantity);
    printf("小计: %.2f\n", subtotal);
    printf("税费: %.2f\n", tax);
    printf("最终金额: %.2f\n", finalPrice);
    printf("累计销量: %d\n", totalSold);

    return 0;
}

⚠️ 常见易错点

  • 未初始化变量:局部变量如果不初始化,其值是随机的,使用前务必赋值。
  • 作用域混淆:在内部块中定义同名变量会“隐藏”外部变量,注意区分。
  • const 变量并非真正不可改:通过指针可以绕过 const 限制(不推荐),但直接修改会编译报错。
  • #define 宏的副作用:如 #define SQUARE(x) x*xSQUARE(2+3) 时会变成 2+3*2+3,正确写法应加括号 #define SQUARE(x) ((x)*(x))
  • 忘记 extern 声明:跨文件使用全局变量时,需要在其他文件中用 extern 声明,否则会出现链接错误。

变量与常量是C语言程序的基础,掌握它们的声明、作用域和存储类别能帮助你写出更高效、更健壮的代码。 下一章我们将学习运算符与表达式,开始构建更复杂的逻辑。