C语言基础:变量与进制详解
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自动转换为floatprintf("结果: %.1f\n", result); // 输出: 13.5return 0;
}
宽类型转窄类型(可能丢失精度)
#include <stdio.h>int main() {// 浮点数转整数(截断小数部分)double pi = 3.14159;int integer_pi = pi; // 结果为3,小数部分被截断// 大整数转小整数(可能溢出)int large = 322; // 322的二进制:101000010char small = large; // 只保留低8位:01000010 = 66printf("原始值: %.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.0float division2 = (float)7 / 3; // 浮点除法,结果为2.333...printf("result1: %d\n", result1); // 输出: 17printf("result2: %d\n", result2); // 输出: 17printf("整数除法: %.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 = 0return 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, // 自动赋值为0TUESDAY, // 自动赋值为1WEDNESDAY, // 自动赋值为2THURSDAY, // 自动赋值为3FRIDAY, // 自动赋值为4SATURDAY, // 自动赋值为5SUNDAY // 自动赋值为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; // 人口数量,用intlong long distance = 9460730472580800LL; // 光年距离,用long longfloat temperature = 36.5f; // 体温,用float足够double pi = 3.141592653589793; // 高精度圆周率,用doublechar grade = 'A'; // 单个字符,用charbool is_student = true; // 逻辑值,用boolprintf("学生数量: %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语言程序。