🛡️

身份验证

答对题目即可进入,验证你是谁

剩余尝试次数:3

变量与数据类型 — 存储你的数据

C语言学习教程

变量与数据类型 — 存储你的数据

🌟 课前故事:你的储物柜

假设你走进学校体育馆,教练递给你一把更衣柜的钥匙,说:“这是你的柜子,你可以把运动服、球鞋、水壶放进去。需要的时候随时来取。”

这个”储物柜”就是C语言中的变量

没有变量,程序就像一个人没有记忆——上一秒算出来的结果,下一秒就忘了。有了变量,程序才能”记住”信息、处理数据、做出判断。

今天,我们就来学习如何给程序”装上记忆”。


📖 概念讲解:变量三要素

什么是变量?

变量(Variable)是内存中的一块命名存储空间,用来存放程序运行中需要用到的数据。

每个变量有三个核心属性:

┌──────────────────────────────────────────────┐
│                    变量                        │
│                                              │
│  ① 变量名    ② 数据类型    ③ 变量的值        │
│   (name)      (type)        (value)          │
│                                              │
│  例子:                                      │
│  int age = 18;                               │
│   ↑   ↑    ↑                                 │
│   类型 名  值                                 │
└──────────────────────────────────────────────┘

为什么需要变量?

  1. 存储数据:程序需要记住用户的输入、计算结果、中间状态
  2. 重复使用:一次存储,多次读取,不用每次重新计算
  3. 可修改性:变量的值可以动态改变,适应不同场景
  4. 代码可读int studentCount = 30; 比直接写 30 更容易理解

什么时候用变量?

任何需要”记住”数据的地方:


📊 变量在内存中长什么样?(可视化)

计算机内存(简化视图)
┌──────────────────────────────────────────────┐
│ 地址: 0x1000                                │
│ ┌────────────┬────────────┬────────────┐     │
│ │  age       │  score     │  grade     │     │
│ │  (int)     │  (float)   │  (char)    │     │
│ │  4字节     │  4字节     │  1字节     │     │
│ │  ┌──────┐  │  ┌──────┐  │  ┌──┐      │     │
│ │  │  18  │  │  │ 95.5 │  │  │A │      │     │
│ │  └──────┘  │  └──────┘  │  └──┘      │     │
│ └────────────┴────────────┴────────────┘     │
│                                              │
│  声明:int age = 18;                         │
│  意思:在内存中找块地方(4字节),           │
│        命名为 "age",把 18 放进去            │
└──────────────────────────────────────────────┘

当你写 int age = 18; 时,计算机做了三件事:

  1. 分配空间:在内存中预留4个字节(因为int占4字节)
  2. 贴标签:给这块空间起名叫 age
  3. 写数据:把数字 18 的二进制形式存入这片空间

以后每当你使用 age 这个名字,计算机就知道去那个位置读取或修改数据。


📊 基本数据类型详解

类型关键字占内存大致范围用途示例
整数int4 字节-2,147,483,648 ~ 2,147,483,647年龄、人数、计数int age = 18;
小数(单精度)float4 字节~7位有效数字身高、成绩、价格float pi = 3.14f;
小数(双精度)double8 字节~15位有效数字科学计算、高精度金额double e = 2.71828;
字符char1 字节-128 ~ 127(ASCII)单个字母、符号char grade = 'A';

为什么有这么多类型?

问题:为什么不用一种类型装所有东西?
答案:内存是有限的,按需分配最省空间

┌──────────┐  ┌──────────┐  ┌──────────┐
│ 年龄 18  │  │ 圆周率    │  │ 等级 A   │
│          │  │ 3.14159  │  │          │
│ 用 int   │  │ 用 float │  │ 用 char  │
│ (4字节)  │  │ (4字节)  │  │ (1字节)  │
└──────────┘  └──────────┘  └──────────┘

如果全用 double (8字节):
年龄占8字节(太浪费!)
等级占8字节(太浪费!)

int — 整数类型

int age = 18;            // 正整数
int temperature = -5;    // 负整数
int zero = 0;            // 零
int big = 2147483647;    // int 能装的最大值
// int overflow = 2147483648; // 超出范围,结果不可预料!

int 的小秘密——溢出:

int max_value = 2147483647;  // int 的最大值
printf("最大值: %d\n", max_value);
max_value = max_value + 1;   // 加1
printf("溢出后: %d\n", max_value); // 变成 -2147483648!(回环)

就像汽车的里程表——达到最大值后,又从头开始。

float 和 double — 浮点数类型

float pi = 3.14159f;       // f 后缀表示这是 float
float score = 95.5f;       // 考试分数
double e = 2.718281828;    // double 不需要后缀
double g = 9.80665;        // 重力加速度

// 科学计数法
float tiny = 1.5e-3;       // 0.0015
double huge = 3.0e8;       // 300000000(光速)

float vs double 怎么选?

float f = 1.0f / 3.0f;
double d = 1.0 / 3.0;

printf("float:  %.10f\n", f);  // 0.3333333433 ← 有误差
printf("double: %.10f\n", d);  // 0.3333333333 ← 更精确

char — 字符类型

char letter = 'A';         // 大写字母
char digit = '7';          // 数字字符(注意:这是字符'7',不是数字7)
char symbol = '@';         // 符号
char newline = '\n';       // 特殊字符(转义字符也可以用char存储)

字符 vs 数字:

char ch = 'A';
printf("字符: %c\n", ch);   // 输出:A
printf("ASCII: %d\n", ch);  // 输出:65(A对应的ASCII码)

// 每个字符在计算机中存的是一个数字(ASCII码)
// 'A'=65, 'B'=66, '0'=48, 'a'=97
字符ASCII码字符ASCII码
’0’48’A’65
’1’49’B’66
’9’57’Z’90
’ ‘32’a’97

💻 声明与初始化

方式1:先声明,后赋值

#include <stdio.h>

int main() {
    int age;          // 声明:告诉编译器"我需要一个叫age的int变量"
    age = 18;         // 赋值:把18放进去

    float score;      // 声明
    score = 95.5f;    // 赋值

    printf("Age: %d, Score: %.1f\n", age, score);
    return 0;
}

注意: 声明但未赋值的变量,里面是随机值(垃圾值)

int x;               // x 的值是随机的!
printf("%d\n", x);   // 可能输出任何数字,比如 -858993460

方式2:声明的同时初始化(推荐)

#include <stdio.h>

int main() {
    int age = 18;              // 声明并初始化
    float score = 95.5f;       // 声明并初始化
    char grade = 'A';          // 声明并初始化

    printf("年龄:%d,成绩:%.1f,等级:%c\n", age, score, grade);
    return 0;
}

推荐理由: 一步到位,避免忘记赋值导致的”垃圾值”问题。

方式3:一次声明多个变量

#include <stdio.h>

int main() {
    // 同类型变量可以一次声明多个
    int x = 1, y = 2, z = 3;

    // 也可以声明时不初始化(不推荐)
    int a, b, c;
    a = 10;
    b = 20;
    c = 30;

    printf("x=%d, y=%d, z=%d\n", x, y, z);
    printf("a=%d, b=%d, c=%d\n", a, b, c);
    return 0;
}

💻 printf 格式占位符大全

printf占位符(也叫格式说明符)来表示”这里要插入一个变量的值”。

占位符对应类型含义示例
%dint十进制整数printf("%d", 42)
%ffloat / double浮点数(默认6位小数)printf("%f", 3.14)
%.2ffloat / double保留2位小数printf("%.2f", 3.14)
%cchar单个字符printf("%c", 'A')
%schar[] (字符串)字符串printf("%s", "Hello")
%xint十六进制整数printf("%x", 255) — 输出 ff
%%(无)百分号本身printf("100%%") — 输出 100%

综合示例

#include <stdio.h>

int main() {
    int age = 20;
    float height = 1.75f;
    double pi = 3.14159265358979;
    char grade = 'A';
    char name[] = "小明";

    printf("我叫%s,今年%d\n", name, age);
    printf("身高%.2f米,成绩等级%c\n", height, grade);
    printf("圆周率:%.2f(保留2位)\n", pi);
    printf("圆周率:%.10f(保留10位)\n", pi);
    printf("年龄的十六进制表示:%x\n", age);
    printf("正确率:100%%\n");  // 输出百分号

    return 0;
}
输出:
我叫小明,今年20岁
身高1.75米,成绩等级A
圆周率:3.14(保留2位)
圆周率:3.1415926536(保留10位)
年龄的十六进制表示:14
正确率:100%

格式控制的进阶用法

#include <stdio.h>

int main() {
    int n = 42;
    float f = 3.14159f;

    // 宽度控制
    printf("|%d|\n", n);        // |42|
    printf("|%5d|\n", n);       // |   42|  (宽度5,右对齐)
    printf("|%-5d|\n", n);      // |42   |  (宽度5,左对齐)
    printf("|%05d|\n", n);      // |00042|  (宽度5,前导零填充)

    // 浮点数控制
    printf("|%f|\n", f);        // |3.141590|  (默认6位)
    printf("|%.2f|\n", f);      // |3.14|      (保留2位)
    printf("|%8.2f|\n", f);     // |    3.14|  (总宽8,2位小数)
    printf("|%-8.2f|\n", f);    // |3.14    |  (左对齐)

    return 0;
}

记忆口诀:


💻 变量命名规则

合法命名规则

  1. 只能包含:字母(A-Z, a-z)、数字(0-9)、下划线(_)
  2. 必须以字母下划线开头(不能数字开头)
  3. 不能使用C语言的关键字(保留字)
  4. 区分大小写ageAgeAGE 是三个不同的变量

命名示例

// ✅ 合法的变量名
int score;           // 小写字母
int player1;         // 字母+数字
int max_value;       // 下划线分隔(蛇形命名法,C语言主流)
int _count;          // 下划线开头(可行但不推荐)
int numberOfStudents; // 驼峰命名法(也可行)

// ❌ 不合法的变量名
int 2player;   // 不能以数字开头!
int if;        // if 是C语言关键字,不能用!
int my score;  // 不能有空格!
int my-score;  // 不能有连字符(-会被当成减号)!

C语言关键字(不能用作变量名)

auto     break   case    char    const   continue
default  do      double  else    enum    extern
float    for     goto    if      int     long
register return  short   signed  sizeof  static
struct   switch  typedef union   unsigned void
volatile while

命名习惯建议

// 🏆 推荐:有意义的英文名
int studentAge = 18;
float examScore = 95.5f;
int itemCount = 10;

// 😕 不推荐:无意义的单个字母(除了循环变量i、j、k)
int a = 18;          // a 代表什么?
float b = 95.5f;     // b 又代表什么?

// 😅 可行但最好避免:拼音
int nianLing = 18;   // 能理解,但不专业

💻 变量的值可以改变

变量之所以叫”变”量,就是因为它的值可以改变。

#include <stdio.h>

int main() {
    int x = 10;                      // x 初始值为 10
    printf("初始值: x = %d\n", x);   // 10

    x = 20;                          // 直接赋值新值
    printf("修改后: x = %d\n", x);   // 20

    x = x + 5;                       // 在自身基础上加 5
    printf("加5后:  x = %d\n", x);   // 25

    x = x * 2;                       // 翻倍
    printf("翻倍后: x = %d\n", x);   // 50

    x = x - 30;                      // 减 30
    printf("减30后: x = %d\n", x);   // 20

    // 总结:每次赋值,"旧值"被覆盖,"新值"取而代之
    return 0;
}

关键理解: 赋值操作 = 是”覆盖”而不是”累加”。x = 20 的意思是”把20放进去,原来有什么不管了”。


💻 综合示例:一个完整的个人信息程序

#include <stdio.h>

int main() {
    // ---- 个人信息变量 ----
    char name[20] = "张三";    // 姓名(字符数组,即字符串)
    int age = 20;               // 年龄
    float height = 1.78f;       // 身高(米)
    double weight = 70.5;       // 体重(公斤)
    char bloodType = 'O';       // 血型
    int studentId = 20240001;   // 学号

    // ---- 输出个人信息 ----
    printf("========================================\n");
    printf("           个人信息卡片                  \n");
    printf("========================================\n");
    printf("  姓名:%s\n", name);
    printf("  学号:%d\n", studentId);
    printf("  年龄:%d\n", age);
    printf("  身高:%.2f\n", height);
    printf("  体重:%.1f 公斤\n", weight);
    printf("  血型:%c\n", bloodType);
    printf("========================================\n");

    // ---- 修改变量的值(模拟"过了一年") ----
    age = age + 1;               // 年龄加1岁
    height = 1.79f;              // 身高长了一厘米
    weight = 71.0;               // 体重变了一点点

    printf("\n  --- 一年后的信息 ---\n\n");
    printf("  年龄:%d\n", age);
    printf("  身高:%.2f\n", height);
    printf("  体重:%.1f 公斤\n", weight);
    printf("========================================\n");

    return 0;
}

从这个例子你学到:


⚠️ 常见错误(5个经典”坑”)

错误1:类型和占位符不匹配

// ❌ 错误代码
int age = 18;
float score = 95.5f;

printf("年龄:%f\n", age);    // 用 %f 输出 int!输出乱码
printf("成绩:%d\n", score);  // 用 %d 输出 float!输出乱码

// 编译器可能不报错,但输出是错的——这叫"未定义行为"

// ✅ 正确代码
int age = 18;
float score = 95.5f;

printf("年龄:%d\n", age);    // %d 配 int
printf("成绩:%.1f\n", score); // %f 配 float

规则: %d → int, %f → float/double, %c → char。谁配谁,不能乱!

错误2:整数赋值小数

// ❌ 错误代码
int price = 9.99;     // 小数赋值给int,被截断为9!
printf("价格:%d\n", price);  // 输出:9,丢失了 .99

// ✅ 正确代码
float price = 9.99f;  // 用 float 存小数
printf("价格:%.2f\n", price);  // 输出:9.99

规则: 要存小数,就用 floatdouble,别用 int

错误3:未初始化就使用变量

// ❌ 错误代码
int x;                 // 声明但未初始化
printf("%d\n", x);     // x 的值是随机的垃圾值!结果不可预料

// ✅ 正确代码
int x = 0;             // 初始化!
printf("%d\n", x);     // 输出确定的值:0

规则: 声明变量的同时,给它一个初始值。不确定是什么就写 = 0

错误4:char 用双引号

// ❌ 错误代码
char grade = "A";      // 双引号表示字符串(多个字符),不是单个字符!

// 编译器报错:incompatible types when assigning to type 'char'

// ✅ 正确代码
char grade = 'A';      // 单引号表示单个字符
char name[] = "A";     // 双引号表示字符串(char数组)

规则: 单个字符用单引号 'A',字符串用双引号 "Hello"

错误5:float 字面量忘写 f

// ❌ 不是错误,但是一个"疏忽"
float pi = 3.14;       // 3.14 默认是 double 类型
                       // 编译器会做一个隐式转换,可能有警告

// ✅ 正确写法
float pi = 3.14f;      // 明确告诉编译器:这是 float
double e = 2.71828;    // double 不需要后缀

规则: float 类型的字面量加 fF 后缀,double 不用。


💡 练习建议

初级练习

  1. 个人信息:声明变量存储你的姓名、年龄、身高,然后打印出来
  2. 四则运算:声明两个 int 变量,输出它们的和、差、积、商
  3. 购物小票:声明变量存储商品名、单价、数量,计算总价并输出

中级练习

  1. 变量交换:有两个变量 a=10, b=20,不用直接赋值,交换它们的值
  2. 格式化对齐:用宽度控制 %5d%-5d 打印一个整齐的表格
  3. 刻意实验:给 int 赋一个超大的值,看看溢出后变成什么

进阶思考

  1. ASCII码探索:打印所有大写字母和它们的ASCII码(提示:字符可以用 %d 输出)
  2. 精度实验:用 float 和 double 分别计算 1.0/3.0,输出到第10位小数,观察差异
  3. sizeof探索:用 sizeof(int)sizeof(float) 查看每种类型在你这台电脑上占多少字节

📝 要点速查清单


🔗 相关主题