变量与基本数据类型 ——程序世界的数字积木
一、数据类型:内存空间的身份证
C语言通过数据类型明确变量占用的内存大小和存储格式。以下是常见类型的核心特性:
1. 整型家族
| 类型 | 内存占用 | 取值范围 | 格式化符号 |
|---|---|---|---|
| char | 1字节 | -128 ~ 127 或 0 ~ 255 | %c |
| short | 2字节 | -32768 ~ 32767 | %hd |
| int | 4字节 | -2147483648 ~ 2147483647 | %d |
| long | 4/8字节 | 取决于系统架构 | %ld |
| long long | 8字节 | -9e18 ~ 9e18 | %lld |
验证代码:
#include <stdio.h>
#include <limits.h>
int main() {
printf("char范围: %d ~ %d\n", CHAR_MIN, CHAR_MAX);
printf("int大小: %zu字节\n", sizeof(int)); // sizeof返回size_t类型
return 0;
}
2. 浮点型家族
| 类型 | 内存占用 | 精度 | 格式化符号 |
|---|---|---|---|
| float | 4字节 | 6-7位有效数字 | %f |
| double | 8字节 | 15-16位有效数字 | %lf |
精度陷阱示例:
float f = 0.1;
if (f == 0.1) { // 条件永远不成立!
printf("Equal!\n");
}
// 因为0.1默认是double类型,float无法精确存储
3. 特殊类型
- void:表示无类型,用于函数返回值或指针
- _Bool:C99新增布尔类型(需包含<stdbool.h>)
二、变量命名与管理
1. 命名规则(铁律)
- 由字母/数字/下划线组成,且不能以数字开头
- 区分大小写:
age与Age是不同的变量 - 禁止使用关键字(如int、return等)
合法命名示例:
int student_count;
float _sensor_data;
char serialNumber[20];
非法命名示例:
int 3d_print; // 数字开头
char switch; // 使用关键字
float user-name; // 含连字符
2. 作用域与生命周期
| 变量类型 | 作用域 | 生命周期 | 存储位置 |
|---|---|---|---|
| 局部变量 | 定义它的代码块内 | 块执行期间 | 栈 |
| 全局变量 | 整个程序 | 程序运行期间 | 数据段 |
| static局部变量 | 定义它的代码块内 | 程序运行期间 | 数据段 |
示例场景:
#include <stdio.h>
int global = 100; // 全局变量
void func() {
static int count = 0; // 静态局部变量
int local = 10; // 普通局部变量
count++;
printf("local:%d count:%d\n", local, count);
}
int main() {
func(); // 输出: local:10 count:1
func(); // 输出: local:10 count:2
// printf("%d", local); 错误!local不可见
return 0;
}
三、常量定义:const vs #define
1. 语法对比
| 特性 | const | #define |
|---|---|---|
| 类型检查 | ✔️ 有明确类型 | ❌ 纯文本替换 |
| 作用域 | 遵循变量作用域规则 | 从定义处到文件结束 |
| 内存分配 | 占用内存空间 | 不分配内存 |
| 调试可见性 | 调试器可查看 | 预处理后消失 |
2. 使用示例
// const常量
const float PI = 3.14159;
const int MAX_USERS = 1000;
// #define宏
#define TAX_RATE 0.15
#define CIRCLE_AREA(r) (PI * (r) * (r)) // 带参数的宏
// 危险宏示例
#define SQUARE(x) x * x
int val = SQUARE(2+3); // 展开为2+3*2+3=11,而非25!
// 应改为:#define SQUARE(x) ((x)*(x))
四、新手避坑指南
-
未初始化变量
int score; printf("%d", score); // 输出随机值! -
作用域混淆
int x = 5; { int x = 10; // 内层x遮蔽外层x printf("%d", x); // 输出10 } -
宏的副作用
#define MAX(a,b) a > b ? a : b int m = MAX(3, 5 + 2); // 展开为3 > 5 + 2 ? 3 : 5 + 2 → 7 -
误用浮点比较
float a = 0.1 + 0.2; if (a == 0.3) { // 永远不成立! // 应使用fabs(a - 0.3) < 1e-6 }
五、总结:变量使用决策模板
✅ 选择数据类型时:
- 需要整数计算 → 根据范围选
int/long - 需要小数存储 → 优先选
double(精度更高) - 存储字符 → 用
char,布尔值 → 用_Bool
✅ 定义常量时:
- 推荐
const(类型安全) - 需要条件编译或字符串拼接 → 用
#define
🚫 避免以下操作:
- 在循环内定义
static变量(导致不可预测的值) - 使用全局变量传递数据(破坏封装性)
- 用
#define定义复杂函数式宏(易引发错误)
终极建议:当你写下int a;时,记住这不是简单的声明——你正在向计算机申请一块内存的使用权。善待每一个变量,就像园丁照料他的植物! 🌱