C语言- Day 2 数据类型与变量
变量 = 一段命名的内存空间。定义一个变量,操作系统在内存中划出一块区域,程序通过变量名访问这块区域。
·
第 2 章 数据类型与变量
2.1 变量的本质
变量 = 一段命名的内存空间。定义一个变量,操作系统在内存中划出一块区域,程序通过变量名访问这块区域。
变量的三要素:
- 名称(name): 用于在代码中引用这块内存
- 类型(type): 决定这块内存有多大,以及如何解释里面的 0/1 序列
- 值(value): 这块内存当前存储的数据
2.2 基本数据类型
| 类型 | 典型大小 | 范围(32位) | 说明 |
|---|---|---|---|
| char | 1 字节 | -128 ~ 127 | 字符或小整数,本质是整型 |
| int | 4 字节 | -2,147,483,648 ~ 2,147,483,647 | 最常用的整数类型 |
| float | 4 字节 | 约 ±3.4×10³⁸,6位有效数字 | 单精度浮点数 |
| double | 8 字节 | 约 ±1.7×10³⁰⁸,15位有效数字 | 双精度浮点,精度更高 |
| void | 无大小 | — | 无类型,用于函数返回值或指针 |
⚠️ 各类型大小依赖平台(16位/32位/64位系统不同)。要知道精确大小,用
sizeof(类型)确认,不要死记硬背。
2.3 整型字面量的三种进制
int a = 255; // 十进制(无前缀)
int b = 0377; // 八进制(以 0 开头)
int c = 0xFF; // 十六进制(以 0x 或 0X 开头)
// 以上三个变量的值完全相同,都是 255
⚠️
int a = 010;的值是 8,不是 10!以 0 开头的整数是八进制。
2.4 类型修饰符与派生类型
| 修饰符 | 含义 | 示例 |
|---|---|---|
| short | 缩小 int 的范围(通常 2 字节) | short int age; |
| long | 扩大 int/double 的范围 | long int population; |
| unsigned | 只允许非负数,正数范围加倍 | unsigned int count; |
| signed | 默认,允许负数(通常省略) | signed int x; |
字面量后缀: 告诉编译器字面量的类型
123u // 或 123U → unsigned int
123L // 或 123l → long int
3.14f // 或 3.14F → float(默认浮点字面量是 double)
2.5 变量的声明与初始化
// 声明(先声明,后使用)
int a;
float price;
// 声明并初始化
int b = 10;
float pi = 3.14f;
// 同行声明多个同类型变量
int x, y, z;
int m = 1, n = 2;
⚠️ 局部变量未初始化,值是随机的(垃圾值),绝对不是 0! 全局变量和 static 变量会自动初始化为 0。
2.6 常量的四种形式
// 1. 字面量常量
100 // 整型字面量
3.14 // 浮点字面量(double 类型)
'A' // 字符常量(单引号,值为 65)
"hello" // 字符串常量(双引号,占 6 字节含 \0)
// 2. #define 宏常量(预处理期替换,无类型)
#define MAX_SIZE 100
#define PI 3.14159
// 3. const 常量(有类型,有作用域,推荐)
const int BUFFER_LEN = 256;
const double PI = 3.14159265358979;
🆚 辨析:
#definevsconst
#define MAX 100→ 纯文本替换,无类型,无作用域,调试时看不到,不能取地址const int MAX = 100→ 有类型(编译器检查),有作用域,调试可见,可以取地址- 工程推荐: 优先用
const;只有需要条件编译或字符串拼接时才用#define
2.7 标识符命名规则
- 由字母、数字、下划线组成,不能以数字开头
- 区分大小写:
count、Count、COUNT是三个不同的标识符 - 不能与 32 个关键字重名
- 长度无硬性限制,但编译器识别的有效长度各异
⚠️ 不要以下划线开头命名(如
_count、__func),这类名称保留给系统实现,可能产生冲突。
工程命名约定(建议):
// 变量、函数:小写下划线(推荐)或小驼峰
int student_count;
void print_menu();
// 常量和宏:全大写下划线
#define MAX_BUFFER 1024
const int PAGE_SIZE = 4096;
// 全局变量:建议加前缀 g_ 以区分
int g_error_code = 0;
2.8 C 语言 32 个关键字
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
⚠️
scanf、printf、NULL、EOF不是关键字,是标准库函数或宏。使用它们需要对应的头文件。
2.9 ASCII 码重点记忆
| 字符范围 | ASCII 值 | 记忆技巧 |
|---|---|---|
'0' ~ '9' |
48 ~ 57 | 数字字符 - '0' = 对应整数值(如 '5' - '0' = 5) |
'A' ~ 'Z' |
65 ~ 90 | 大写字母基准:'A' = 65 |
'a' ~ 'z' |
97 ~ 122 | 小写比大写大 32:'a' - 'A' = 32 |
| 空格 | 32 | 最小的可打印字符 |
'\0'(空字符) |
0 | 字符串结束标志,值为 0,不是字符 0 |
大小写转换: 加减 32 即可
char c = 'a';
char upper = c - 32; // → 'A'
// 或用标准库(更规范):
char upper2 = toupper(c); // 需要 #include <ctype.h>
🆚 辨析:
'0'vs0vs'\0'vsNULL
'0'→ 字符零,ASCII 值为 48,是一个可打印字符0→ 整数零,可以是 int、float 等任意数值类型的零值'\0'→ 空字符,ASCII 值为 0,是字符串的结束标志NULL→ 空指针,值为 0,表示指针不指向任何有效地址
2.10 原码、反码、补码
计算机内部用补码存储有符号整数。理解这个有助于理解位运算和整数溢出。
| 编码方式 | 正数 | 负数(以 -5 举例,8 位) | 说明 |
|---|---|---|---|
| 原码 | 符号位0 + 绝对值 | 10000101 |
直观,但加减法需要单独处理符号位 |
| 反码 | 与原码相同 | 11111010 |
原码除符号位取反 |
| 补码 | 与原码相同 | 11111011 |
反码 + 1,计算机实际使用这种 |
为什么用补码? 补码让加法和减法可以用同一套电路完成,且没有 +0/-0 的问题。
// 验证方法:-5 的补码计算
// 1. 写出 +5 的原码(8位): 00000101
// 2. 除符号位取反(反码): 11111010
// 3. 反码 + 1(补码): 11111011
// 验证:11111011 + 00000101 = 100000000,丢掉最高位进位 = 00000000(0),正确!
2.11 大端模式 vs 小端模式
当一个数据超过 1 字节(如 int 占 4 字节)时,多字节如何在内存中排列,有两种方式:
| 模式 | 规则 | 使用场景 | 举例(0x12345678) |
|---|---|---|---|
| 大端(Big-Endian) | 高位字节存低地址 | 网络传输(TCP/IP 标准) | 低地址→12 34 56 78 |
| 小端(Little-Endian) | 低位字节存低地址 | x86/x64 PC(Intel/AMD) | 低地址→78 56 34 12 |
2.12 数值类型的常见陷阱
整型溢出
#include <limits.h>
int a = INT_MAX; // 2147483647
a = a + 1; // ⚠️ 有符号溢出是未定义行为!结果不可预测
unsigned int b = 0;
b = b - 1; // 无符号溢出:合法,结果是 4294967295(取模回绕)
浮点精度
double a = 0.1 + 0.2;
printf("%.17f\n", a); // 输出:0.30000000000000004
// ⚠️ 不能直接用 == 比较浮点数
if(a == 0.3) ... // 可能永远不成立!
// ✅ 正确做法:判断差值是否足够小
#include <math.h>
if(fabs(a - 0.3) < 1e-9) ... // 在允许误差范围内
隐式截断
double x = 3.9;
int i = x; // i = 3(截断,不是四舍五入!)
int big = 300;
char c = big; // c = 44(300 % 256,高位被截断)
unsigned int u = 10;
int n = -1;
if(n < u) ... // ⚠️ 结果为假!-1 被当作超大无符号数(4294967295)
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)