C语言基础:变量与进制详解
1. 关键字详解
什么是关键字?
关键字是C语言预定义的具有特殊含义的单词,不能用作变量名或函数名。
关键字特点
- 全部由小写字母组成
- 被C语言赋予特殊含义
- 不可修改或重新定义
C语言关键字分类
类型 | 关键字 |
---|---|
控制语句(12个) | break, case, continue, default, do, else, for, goto, if, return, switch, while |
数据类型(12个) | char, enum, double, long, float, int, short, signed, struct, unsigned, union, void |
存储类型(4个) | auto, extern, register, static |
其他(4个) | const, sizeof, typedef, volatile |
版本演进
- C99标准新增:inline, restrict, _Bool, _Complex, _Imaginary
- C11标准新增:_Alignas, _Alignof, _Atomic, _Static_assert, _Noreturn, _Thread_local, _Generic
2. 标识符规范
定义
标识符是程序员为变量、函数、数组等命名时使用的字符序列。
命名规则(必须遵守)
- 只能包含字母、数字、下划线
- 不能以数字开头
- 不能使用关键字
- 区分大小写
- 不允许空格
命名建议(提高代码质量)
- 见名知意:使用有意义的名称
- 避免混淆:不要仅靠大小写区分
- 常量大写:宏定义和常量全大写
- 下划线连接:长变量名用下划线分隔
- 驼峰命名:函数和变量使用小驼峰
示例对比
合法标识符:
a, BOOK1, _sun, MAX_SIZE, Mouse, student23, Football, max, _add, num_1
非法标识符:
$zj, 3sum, ab#cd, 23student, Foot-ball, s.com, b&c, j**p, book-1, tax rate
3. 变量深度解析
为什么需要变量?
变量是程序中的基本存储单元,用于在内存中保存数据。就像现实生活中的容器,可以存放不同类型的物品。
变量的三要素
- 数据类型:决定存储什么类型的数据
- 变量名:用于访问内存中的数据
- 存储值:实际保存的数据内容
变量声明与赋值
声明语法
数据类型 变量名; // 声明变量,为其分配内存空间
赋值操作
int age; // 声明整型变量age
age = 18; // 为变量age赋值
声明并初始化
int age = 18; // 声明的同时进行初始化
多变量处理
int a = 1, b = 2; // 同时声明并初始化多个变量
int x, y, z; // 声明多个变量
x = y = z = 10; // 连续赋值
变量作用域
文件作用域
在源文件顶层声明的变量,从声明位置到文件结束都有效。
int global_var = 100; // 全局变量,文件作用域
int main() {
printf("%d\n", global_var); // 可以访问全局变量
return 0;
}
块作用域
在大括号内声明的变量,只在当前代码块有效。
int main() {
int outer = 10; // 外层变量
if (outer == 10) {
int inner = 20; // 内层变量,只在if块内有效
printf("%d %d\n", outer, inner); // 输出:10 20
}
printf("%d\n", outer); // 正常输出:10
// printf("%d\n", inner); // 错误!inner已超出作用域
return 0;
}
4. 基本数据类型详解
4.1 整数类型
类型分类与内存占用
类型 | 修饰符 | 字节数 | 取值范围 |
---|---|---|---|
short | signed | 2字节 | -32,768 ~ 32,767 |
short | unsigned | 2字节 | 0 ~ 65,535 |
int | signed | 4字节 | -2,147,483,648 ~ 2,147,483,647 |
int | unsigned | 4字节 | 0 ~ 4,294,967,295 |
long long | signed | 8字节 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
实际应用示例
#include <stdio.h>
int main() {
// 声明不同类型的整数变量
short small_num = 100; // 短整型,适合小数值
int normal_num = 1000000; // 标准整型,最常用
long long big_num = 9000000000LL; // 长长整型,适合大数值
// 无符号整型,只能存储非负数
unsigned int positive_num = 4000000000U;
printf("短整型: %d\n", small_num);
printf("标准整型: %d\n", normal_num);
printf("长长整型: %lld\n", big_num);
printf("无符号整型: %u\n", positive_num);
return 0;
}
4.2 浮点类型
类型特点
类型 | 字节数 | 精度 | 适用场景 |
---|---|---|---|
float | 4字节 | 6-7位有效数字 | 一般精度计算 |
double | 8字节 | 15-16位有效数字 | 高精度计算(推荐) |
long double | 12字节 | 更高精度 | 科学计算 |
温度转换实例
#include <stdio.h>
int main() {
float fahrenheit, celsius; // 声明华氏温度和摄氏温度变量
printf("请输入华氏温度: ");
scanf("%f", &fahrenheit); // 从键盘输入华氏温度
// 华氏转摄氏公式: C = 5/9 * (F - 32)
celsius = (5.0 / 9.0) * (fahrenheit - 32.0);
printf("华氏温度: %.1f°F\n", fahrenheit);
printf("摄氏温度: %.1f°C\n", celsius);
return 0;
}
科学计数法表示
double large_num = 1.23e6; // 等于 1,230,000
double small_num = 4.56e-3; // 等于 0.00456
float precise = 3.14159f; // float类型需要f后缀
4.3 字符类型
基本概念
字符类型用于存储单个字符,占用1个字节内存。
三种表示方式
#include <stdio.h>
int main() {
// 方式1:直接使用字符
char letter = 'A'; // 存储字符A
// 方式2:使用ASCII码值
char ascii_char = 65; // 65对应字符A
// 方式3:使用转义字符
char newline = '\n'; // 换行符
char tab = '\t'; // 制表符
char quote = '\''; // 单引号字符
printf("字符: %c\n", letter);
printf("ASCII值: %d\n", letter);
printf("相同字符: %c\n", ascii_char);
return 0;
}
常用转义字符
转义字符 | 含义 | 用途 |
---|---|---|
\n | 换行符 | 光标移到下一行开头 |
\t | 制表符 | 光标移到下一个Tab位置 |
’ | 单引号 | 在字符中表示单引号 |
" | 双引号 | 在字符串中表示双引号 |
\ | 反斜杠 | 表示反斜杠字符 |
\0 | 空字符 | 字符串结束标志 |
4.4 布尔类型
C89标准(传统方式)
#include <stdio.h>
int main() {
int is_student = 1; // 1表示真(是学生)
int is_teacher = 0; // 0表示假(不是老师)
if (is_student) {
printf("这是一个学生\n");
}
if (!is_teacher) {
printf("这不是老师\n");
}
return 0;
}
C99标准(现代方式)
#include <stdio.h>
#include <stdbool.h> // 包含布尔类型头文件
int main() {
bool is_online = true; // 声明布尔变量并赋值为真
bool is_offline = false; // 声明布尔变量并赋值为假
if (is_online) {
printf("用户在线\n");
}
return 0;
}
5. 类型转换机制
5.1 自动类型转换
窄类型转宽类型(安全转换)
#include <stdio.h>
int main() {
// 整数类型自动提升
char small = 10; // char类型(1字节)
int medium = small; // 自动转换为int类型(4字节)
long big = medium; // 自动转换为long类型(8字节)
// 浮点数类型自动提升
float single = 3.14f; // float类型(4字节)
double precise = single; // 自动转换为double类型(8字节)
// 混合运算自动转换
int integer = 10;
float decimal = 3.5f;
float result = integer + decimal; // int自动转换为float
printf("结果: %.1f\n", result); // 输出: 13.5
return 0;
}
宽类型转窄类型(可能丢失精度)
#include <stdio.h>
int main() {
// 浮点数转整数(截断小数部分)
double pi = 3.14159;
int integer_pi = pi; // 结果为3,小数部分被截断
// 大整数转小整数(可能溢出)
int large = 322; // 322的二进制:101000010
char small = large; // 只保留低8位:01000010 = 66
printf("原始值: %.5f\n", pi);
printf("转换后: %d\n", integer_pi);
printf("大整数: %d\n", large);
printf("小整数: %d\n", small);
return 0;
}
5.2 强制类型转换
当需要明确进行类型转换时,使用强制转换操作符。
语法格式: (目标类型)变量或表达式
#include <stdio.h>
int main() {
double x = 12.8;
int y = 5;
// 强制转换示例
int result1 = (int)x + y; // 先将x转为int(12),再相加
int result2 = (int)(x + y); // 先相加(17.8),再转为int(17)
// 精度控制
float division1 = 7 / 3; // 整数除法,结果为2.0
float division2 = (float)7 / 3; // 浮点除法,结果为2.333...
printf("result1: %d\n", result1); // 输出: 17
printf("result2: %d\n", result2); // 输出: 17
printf("整数除法: %.3f\n", division1);
printf("浮点除法: %.3f\n", division2);
return 0;
}
5.3 溢出问题处理
向上溢出示例
#include <stdio.h>
int main() {
unsigned char max_value = 255; // unsigned char最大值
printf("溢出前: %d\n", max_value);
max_value = max_value + 1; // 发生向上溢出
printf("溢出后: %d\n", max_value); // 输出: 0
// 解释:255的二进制是11111111,加1变成100000000
// 由于unsigned char只有8位,最高位被丢弃,结果变成00000000 = 0
return 0;
}
6. 常量定义方法
6.1 字面常量
直接在代码中写出的数值。
int number = 42; // 42是整型字面常量
float pi = 3.14f; // 3.14f是浮点型字面常量
char grade = 'A'; // 'A'是字符型字面常量
6.2 宏定义常量
#include <stdio.h>
#define PI 3.14159 // 定义圆周率常量
#define MAX_STUDENTS 100 // 定义最大学生数
#define SCHOOL_NAME "清华大学" // 定义学校名称
int main() {
double radius = 5.0; // 圆的半径
double area; // 圆的面积
// 使用宏定义常量计算圆面积
area = PI * radius * radius;
printf("学校: %s\n", SCHOOL_NAME);
printf("圆的半径: %.1f\n", radius);
printf("圆的面积: %.2f\n", area);
return 0;
}
6.3 const限定符
#include <stdio.h>
int main() {
const float TAX_RATE = 0.13f; // 声明税率常量
const int DAYS_IN_WEEK = 7; // 声明一周天数常量
float salary = 5000.0f; // 工资
float tax; // 税金
// 使用const常量计算税金
tax = salary * TAX_RATE;
printf("工资: %.2f元\n", salary);
printf("税率: %.0f%%\n", TAX_RATE * 100);
printf("税金: %.2f元\n", tax);
// TAX_RATE = 0.15f; // 错误!const变量不能修改
return 0;
}
6.4 枚举常量
#include <stdio.h>
// 定义星期枚举
enum Weekday {
MONDAY, // 自动赋值为0
TUESDAY, // 自动赋值为1
WEDNESDAY, // 自动赋值为2
THURSDAY, // 自动赋值为3
FRIDAY, // 自动赋值为4
SATURDAY, // 自动赋值为5
SUNDAY // 自动赋值为6
};
int main() {
enum Weekday today = FRIDAY; // 声明今天是星期五
printf("今天是星期: %d\n", today); // 输出: 4
// 使用枚举进行条件判断
if (today == FRIDAY) {
printf("明天是周末!\n");
}
return 0;
}
7. 输入输出函数详解
7.1 scanf()函数深度解析
基本用法
scanf("格式字符串", &变量1, &变量2, ...);
格式字符串说明
%d
:读取整数%f
:读取浮点数%c
:读取字符%s
:读取字符串
实际应用示例
#include <stdio.h>
int main() {
int age; // 年龄变量
float height; // 身高变量
char grade; // 成绩等级变量
// 提示用户输入
printf("请输入您的年龄: ");
scanf("%d", &age); // 读取整数,注意&符号
printf("请输入您的身高(米): ");
scanf("%f", &height); // 读取浮点数
printf("请输入成绩等级: ");
scanf(" %c", &grade); // 读取字符,注意空格
// 输出结果
printf("\n个人信息汇总:\n");
printf("年龄: %d岁\n", age);
printf("身高: %.2f米\n", height);
printf("成绩: %c等\n", grade);
return 0;
}
多变量同时输入
#include <stdio.h>
int main() {
int year, month, day; // 年、月、日变量
// 方式1:空格分隔输入
printf("请输入年 月 日(空格分隔): ");
scanf("%d %d %d", &year, &month, &day);
// 方式2:特定分隔符输入
printf("请输入日期(格式yyyy-mm-dd): ");
scanf("%d-%d-%d", &year, &month, &day);
printf("您输入的日期是: %d年%d月%d日\n", year, month, day);
return 0;
}
7.2 字符输入输出函数
#include <stdio.h>
int main() {
char input_char; // 输入字符变量
printf("请输入一个字符: ");
input_char = getchar(); // 从键盘读取一个字符
printf("您输入的字符是: ");
putchar(input_char); // 输出字符
putchar('\n'); // 输出换行符
return 0;
}
8. 进制系统详解
8.1 进制概念
各进制特点
进制 | 数字组成 | 进位规则 | C语言表示 | 应用场景 |
---|---|---|---|---|
二进制 | 0-1 | 满二进一 | 0b前缀 | 计算机底层 |
八进制 | 0-7 | 满八进一 | 0前缀 | 文件权限 |
十进制 | 0-9 | 满十进一 | 直接写 | 日常计算 |
十六进制 | 0-9,A-F | 满十六进一 | 0x前缀 | 内存地址 |
进制表示示例
#include <stdio.h>
int main() {
// 同一个数值的不同进制表示
int decimal = 255; // 十进制表示
int binary = 0b11111111; // 二进制表示(C99标准)
int octal = 0377; // 八进制表示
int hexadecimal = 0xFF; // 十六进制表示
// 验证它们是否相等
printf("十进制: %d\n", decimal);
printf("二进制: %d\n", binary);
printf("八进制: %d\n", octal);
printf("十六进制: %d\n", hexadecimal);
// 以不同进制格式输出同一个数
int number = 100;
printf("\n数字100的不同进制表示:\n");
printf("十进制: %d\n", number);
printf("八进制: %o\n", number);
printf("十六进制: %x\n", number);
printf("带前缀的八进制: %#o\n", number);
printf("带前缀的十六进制: %#x\n", number);
return 0;
}
8.2 进制转换实例
手动转换演示
#include <stdio.h>
// 十进制转二进制函数
void decimal_to_binary(int num) {
printf("十进制 %d 转二进制过程:\n", num);
if (num == 0) {
printf("二进制: 0\n");
return;
}
int binary[32]; // 存储二进制位
int index = 0; // 数组索引
// 除2取余法
while (num > 0) {
binary[index] = num % 2; // 取余数
printf("第%d步: %d ÷ 2 = %d 余 %d\n",
index + 1, num, num / 2, binary[index]);
num = num / 2; // 取商
index++;
}
// 逆序输出得到二进制结果
printf("二进制结果: ");
for (int i = index - 1; i >= 0; i--) {
printf("%d", binary[i]);
}
printf("\n\n");
}
int main() {
decimal_to_binary(25); // 演示25转二进制的过程
decimal_to_binary(100); // 演示100转二进制的过程
return 0;
}
9. 综合实战案例
案例:学生成绩管理系统
#include <stdio.h>
#include <stdbool.h>
// 定义成绩等级枚举
enum Grade {
FAIL, // 不及格 (0-59)
PASS, // 及格 (60-69)
GOOD, // 良好 (70-84)
EXCELLENT // 优秀 (85-100)
};
int main() {
// 学生信息变量
char student_id[20]; // 学号
int age; // 年龄
float math_score; // 数学成绩
float english_score; // 英语成绩
float average; // 平均分
enum Grade final_grade; // 最终等级
bool is_passed; // 是否通过
// 输入学生信息
printf("=== 学生成绩管理系统 ===\n");
printf("请输入学号: ");
scanf("%s", student_id); // 字符串不需要&符号
printf("请输入年龄: ");
scanf("%d", &age);
printf("请输入数学成绩: ");
scanf("%f", &math_score);
printf("请输入英语成绩: ");
scanf("%f", &english_score);
// 计算平均分
average = (math_score + english_score) / 2.0f;
// 判断等级
if (average >= 85) {
final_grade = EXCELLENT;
} else if (average >= 70) {
final_grade = GOOD;
} else if (average >= 60) {
final_grade = PASS;
} else {
final_grade = FAIL;
}
// 判断是否通过
is_passed = (average >= 60);
// 输出结果
printf("\n=== 成绩报告 ===\n");
printf("学号: %s\n", student_id);
printf("年龄: %d岁\n", age);
printf("数学成绩: %.1f分\n", math_score);
printf("英语成绩: %.1f分\n", english_score);
printf("平均分: %.1f分\n", average);
// 输出等级
printf("成绩等级: ");
switch (final_grade) {
case EXCELLENT:
printf("优秀\n");
break;
case GOOD:
printf("良好\n");
break;
case PASS:
printf("及格\n");
break;
case FAIL:
printf("不及格\n");
break;
}
// 输出是否通过
if (is_passed) {
printf("考试结果: 通过\n");
} else {
printf("考试结果: 未通过,需要补考\n");
}
return 0;
}
10. 编程注意事项
10.1 输入法问题
在编写C语言代码时,必须使用英文输入法:
// 正确写法(英文标点)
printf("Hello World\n");
// 错误写法(中文标点)
printf("Hello World\n"); // 编译错误!
10.2 变量初始化重要性
#include <stdio.h>
int main() {
int uninitialized; // 未初始化变量,值不确定
int initialized = 0; // 已初始化变量,值确定
// 未初始化变量可能包含垃圾值
printf("未初始化变量: %d\n", uninitialized); // 输出不确定
printf("已初始化变量: %d\n", initialized); // 输出: 0
// 正确做法:声明时就初始化
int safe_variable = 100;
printf("安全变量: %d\n", safe_variable);
return 0;
}
10.3 数据类型选择建议
#include <stdio.h>
int main() {
// 根据数据范围选择合适的类型
short student_count = 50; // 学生数量,用short足够
int population = 1400000000; // 人口数量,用int
long long distance = 9460730472580800LL; // 光年距离,用long long
float temperature = 36.5f; // 体温,用float足够
double pi = 3.141592653589793; // 高精度圆周率,用double
char grade = 'A'; // 单个字符,用char
bool is_student = true; // 逻辑值,用bool
printf("学生数量: %d人\n", student_count);
printf("人口数量: %d人\n", population);
printf("光年距离: %lld千米\n", distance);
printf("体温: %.1f°C\n", temperature);
printf("圆周率: %.15f\n", pi);
printf("成绩等级: %c\n", grade);
printf("是否为学生: %s\n", is_student ? "是" : "否");
return 0;
}
总结
本章介绍了C语言的基础概念:
- 关键字:C语言预定义的特殊单词
- 标识符:程序员自定义的名称
- 变量:存储数据的内存空间
- 数据类型:定义数据的种类和范围
- 类型转换:不同类型间的数据转换
- 常量:程序运行期间不变的值
- 输入输出:与用户交互的基本方法
- 进制系统:不同的数值表示方法
掌握这些基础知识,是学习C语言的重要基石。在实际编程中,要注意选择合适的数据类型、正确初始化变量、避免类型转换带来的精度损失,这样才能写出高质量的C语言程序。