电子商务网站建设与维护 教材,俄语网站建设注意事项,服务器搭建要多少钱,东营企业自助建站点关注不迷路哟。你的点赞、收藏#xff0c;一键三连#xff0c;是我持续更新的动力哟#xff01;#xff01;#xff01;
主页#xff1a;
一位搞嵌入式的 genius-CSDN博客https://blog.csdn.net/m0_73589512?spm1000.2115.3001.5343
目录
Day02→数据类型#xf…点关注不迷路哟。你的点赞、收藏一键三连是我持续更新的动力哟
主页
一位搞嵌入式的 genius-CSDN博客https://blog.csdn.net/m0_73589512?spm1000.2115.3001.5343
目录
Day02→数据类型上
数据类型分类
基本数据类型
整形数据类型
字符型数据类型
实型数据类型
构造数据类型
特殊数据类型
布尔类型详解
基本概念
使用注意事项
预处理分析
知识小结
Day02→数据类型下
char类型
short 类型
short 类型与 unsigned short 类型的定义
short 类型与 int 类型的长度区别
示例打印类型长度
short 类型值域的分析
int 类型
limits.h 头文件
头文件作用
文件位置与包含方式
主要宏定义内容
实际应用示例
使用建议
知识小结
Day02→常量
常量定义
基本数据类型常量
1整型常量
2浮点型常量
标识常量宏定义
1使用规范
2优势与局限
基本数据类型的常量补充细节
1整型常量
2浮点常量
3指数常量
4字符常量
5字符串常量
应用案例精选
例题字符常量运算
例题宏定义的文本替换
知识小结
Day02→嵌入式开发变量一
作业讲解
变量的基础
1变量的概念
2变量的存储空间
变量的说明
变量的存储类型
1auto
2register
总结与思考
1内容总结
知识小结
Day02→嵌入式开发变量二
static 存储类型
定义与特性
1static 局部变量示例
代码对比
关键现象
2static 局部变量的特点
extern 存储类型
定义与使用条件
1extern 全局变量示例
典型错误
正确用法
2总结与思考
知识小结
Day02→运算符1
算术运算符
1C 语言提供的算术运算符
例题整数加减乘除运算
例题double 类型运算
关系运算符
1C 语言的关系运算符
例题关系运算符运算
逻辑运算符
1逻辑非 ! 运算符的运算律
例题逻辑非运算符使用
2逻辑与 运算符的运算规律
例题if 条件语句逻辑与运算
3逻辑或 || 运算符的运算规律
例题逻辑或运算符使用
运算符总结
1. 算术运算符
2. 关系运算符
3. 逻辑运算符
4. 例题逻辑运算求值
知识小结
Day02→运算符2
位运算符基础
1C 语言的位运算符
位逻辑反运算符~
位逻辑与运算符
位逻辑或运算符|
位逻辑异或运算符^
2位移位运算
移位运算的一般形式
位运算与移位操作
1. 十六进制与二进制转换
2. 左移运算原理
3. 例题验证左移运算
4. 移位运算的数学本质
知识小结
Day02→运算符3
位运算的核心应用与例题解析
1. 思考
2. 例题无符号数置 1
3. 例题无符号数清 0
4. 例题十进制转十六进制位运算优化
位运算的应用价值与学习建议
应用价值
学习建议
知识小结
Day02→运算符4
赋值运算符
1基本赋值运算符
2赋值复合运算符
例题赋值复合运算符应用
特殊运算符
1条件运算符三目运算符
例题三目运算符应用
例题三目运算符与自增结合
2逗号运算符
例题逗号运算符应用
3sizeof 运算符
运算符的优先级
1优先级表核心规则
例题运算符优先级应用
知识小结 Day02→数据类型上
数据类型分类
基本数据类型 分类依据根据存储范围和正负特性选择数据类型主要考虑数据大小范围和是否需要存储负数。 主要类型 整形包括有符号signed和无符号unsigned两种形式。 字符型char 类型实际也分有符号和无符号两种。 实型float 和 double 用于存储小数。 枚举型enum 类型。 存储特性 有符号数可存储正负数无符号数只能存储≥0 的数。 范围从小到大short int long long long。
整形数据类型 符号区分 有符号数用 signed 表示可存储正负数。 无符号数用 unsigned 表示只能存储≥0 的数。 范围区分 short短整型。 int基本整型。 long长整型。 long long超长整型。 选择原则 根据数据是否可能为负数选择有 / 无符号。 根据数据大小范围选择合适的数据类型。
字符型数据类型 基本形式char 类型。 特殊性质 实际上也分为有符号和无符号两种形式。 字符的 ASCII 码值可以视为某种形式的整型。 存储特性 可存储单个字符。 底层存储的是字符对应的 ASCII 码值。
实型数据类型 主要类型 float单精度浮点型。 double双精度浮点型。 应用场景 用于存储小数数据。 需要更高精度时使用 double 类型。
构造数据类型 定义用户自定义的数据类型非基础类型。 主要类型 数组。 结构体struct。 共用体union。 特点 需要用户自行定义。 可以组合基本类型构建更复杂的数据结构。
特殊数据类型 指针类型 用于存储内存地址。 是 C 语言的重要特性。 空类型void 用于说明不返回值的函数。 也可用于指向类型的指针。
布尔类型详解
基本概念 类型名称bool。 值域 true非零值通常为 1。 false零值。 赋值方式 直接赋值为 true/false。 赋值为非零 / 零值。 判断规则非零值为真零值为假。
使用注意事项 头文件要求 需要包含stdbool.h头文件。 否则会报 “unknown type name” 错误。 底层实现 实际是 C99 标准引入的_Bool类型。 true 和 false 是宏定义分别为 1 和 0。 赋值特性 赋值为负数-1时仍视为真值非零。 但实际存储时会转换为 1。
预处理分析 预处理命令gcc -E bool.c -o bool.i。 头文件位置/usr/lib/gcc/x86_64-linux-gnu/11/include/stdbool.h。 宏定义内容 #define bool _Bool
#define true 1
#define false 0 替代方案 可直接使用_Bool类型。 但仍需头文件来使用 true/false。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数数据类型概述C 语言学习路径数据类型→常量 / 变量→运算符→控制语句→输入输出→数组 / 字符串→指针 / 函数数据类型分类逻辑基本类型 / 构造类型 / 指针类型 / 空类型⭐⭐布尔类型- 需引入 stdbool.h 头文件- 本质为_Bool 基本类型C99 新增- 真值规则非零为真true1零为假false0- 未引入头文件时直接使用 bool 会报错- 宏定义陷阱true/false 实际为头文件定义的宏值固定为 1/0⭐⭐⭐整型分类逻辑根据范围short/int/long/long long和符号性signed/unsigned划分- long long 与 long 范围差异- 字符型本质属于特殊整型可参与数值运算⭐⭐⭐⭐浮点型float单精度与 double双精度的存储精度差异默认小数常量类型为 double需加 f 后缀显式声明为 float⭐⭐类型转换- 隐式转换规则小类型→大类型- 强制转换语法(目标类型) 变量符号扩展问题如 char 转 int 时符号位填充⭐⭐⭐编程实践要点- 强调同步编码验证如布尔值打印测试- 预处理命令 gcc -E 分析头文件展开易错点布尔变量赋值为 - 1 时实际存储值为 1因宏替换 Day02→数据类型下
char类型
1 #include stdio.h2 #include stdbool.h3 4 // argc命令行参数的个数包含程序名本身5 6 int main(int argc, char *argv[]) {7 unsigned char ch;8 ch -1;9 printf(ch %d %c\n,ch,ch);10 11 return 0;12 13 }
那这份代码为什么最后打印出来的是255
解答
在这段代码中打印出 255 主要和 unsigned char 类型以及数据的存储、类型转换规则有关以下是详细解释
1. 数据存储
char 类型如果是有符号的其取值范围是 -128 到 127如果是 unsigned char取值范围是 0 到 255 。在代码中变量 ch 被声明为 unsigned char 类型。
当执行 ch -1; 时-1 是一个有符号整数在计算机中有符号整数以补码形式存储-1 的 8 位补码是 1111 1111 。将 -1 赋值给 unsigned char 类型的变量 ch 时编译器会直接把 -1 的补码值 1111 1111 存储到 ch 对应的内存空间中 。因为 unsigned char 类型不区分符号位所以这个 1111 1111 就被解释为无符号数 。
2. 类型转换与打印
printf 函数中%d 格式说明符用于打印整数。当使用 %d 打印 unsigned char 类型的变量 ch 时会发生类型提升。由于 unsigned char 是小于 int 类型的整型在表达式求值时会将 unsigned char 类型的值提升为 int 类型 。
对于 unsigned char 类型在提升过程中会在高位补 0 1111 1111 提升为 int 类型后就是 0000 0000 0000 0000 0000 0000 1111 1111 对应的无符号十进制值就是 255 所以打印出 255 。
而对于 %c 格式说明符它会将 ch 的值作为 ASCII 码值来解析对应的字符。ASCII 码中码值 255 对应的字符是不可打印的控制字符所以通常会看到一个乱码或者不显示字符 。
总结来说是 unsigned char 类型对数据的解释方式以及 printf 函数在打印时的类型提升规则导致了打印出 255 这个结果。
short 类型
short 类型与 unsigned short 类型的定义 存储长度short 类型占用 2 个字节存储空间。 有符号范围signed short 值域为 - 32768~32767。 无符号范围unsigned short 值域为 0~65535。
short 类型与 int 类型的长度区别 操作系统影响在 32 位系统中short 长度为 2 字节int 长度为 4 字节。 符号处理两者都可以存储负数使用 signed 修饰符表示有符号类型。
示例打印类型长度 测量方法使用 sizeof 运算符获取类型长度。 典型结果 bool 类型1 字节 char 类型1 字节 short 类型2 字节 int 类型4 字节 实现限制sizeof 最小单位为字节不能测量更小的位数。
short 类型值域的分析 位数计算2 字节 16 位无符号最大值为(2^{16}-165535)。 有符号范围-32768 到 32767最高位为符号位。 应用场景适合存储 6 万以下的数值如工资等中等规模数据。
int 类型 存储长度固定占用 4 字节存储空间。 无符号范围0~4294967295(2^{32}-1)。 有符号范围-2147483648~2147483647。 空间规模相当于 4GB 的寻址空间。 计算技巧可通过(2^{n}-1)n 为总位数快速估算最大取值范围。
limits.h 头文件
头文件作用 数据类型范围查询当数据类型长度较长时如 int、long 等直接记忆其值域范围较为困难limits.h 头文件提供了各数据类型的范围宏定义。 避免手动计算通过包含该头文件可直接使用预定义的常量值无需手动计算数据类型的边界值。
文件位置与包含方式 标准位置位于 /usr/include/ 目录下。 包含语法#include limits.h。
主要宏定义内容 字符型范围 有符号 char: -128~127SCHAR_MIN~SCHAR_MAX 无符号 char: 0~255UCHAR_MAX 字节定义: CHAR_BIT 宏定义为 8表示 1 字节 8 位 short 类型范围 有符号 short: -32768~32767SHRT_MIN~SHRT_MAX 无符号 short: 0~65535USHRT_MAX 整型范围 有符号 int: -2147483648~2147483647INT_MIN~INT_MAX 无符号 int: 0~4294967295UINT_MAX long 类型范围 有符号 long: -9223372036854775808~9223372036854775807LONG_MIN~LONG_MAX 无符号 long: 0~18446744073709551615ULONG_MAX
实际应用示例 程序演示
#include stdio.h
#include limits.h
int main() {printf(有符号int最小值%d\n, INT_MIN);printf(有符号int最大值%d\n, INT_MAX);printf(无符号int最大值%u\n, UINT_MAX);return 0;
} 输出结果
有符号int最小值-2147483648
有符号int最大值2147483647
无符号int最大值4294967295
使用建议 编程实践在需要获取数据类型边界值时直接使用 limits.h 中的宏定义。 记忆技巧只需记住各类型字节长度具体范围可通过头文件查询。 验证方法编写简单测试程序打印各宏定义值与理论值进行比对。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数布尔类型基本数据类型介绍可赋值的范围及长度布尔类型的实际存储方式通过整型实现⭐⭐字符型 (char)1 字节长度有符号 (-128~127) 和无符号 (0~255) 范围负 128 的特殊补码表示 (10000000)ASCII 码转换规则⭐⭐⭐⭐整型 (short/int)short (2 字节) 范围-32768~32767int (4 字节) 范围-2147483648~214748364732/64 位系统下 long 类型长度差异使用 sizeof 测试环境⭐⭐⭐数据范围计算二进制补码原理原码 / 反码 / 补码转换负数的补码计算规则边界值溢出问题如 128 变成 - 128⭐⭐⭐⭐limits.h 头文件预定义各类型极值常量CHAR_MIN/CHAR_MAX 等实际开发中替代手动计算范围的方法⭐⭐类型安全赋值越界的隐式转换风险如 char 赋 128 转为 - 128编译器不报错但运行异常的情况处理⭐⭐⭐⭐ASCII 编码字符与整数的映射关系如 65 对应 A非打印字符的显示问题如 12 Day02→常量
常量定义 概念常量是在整个程序运行期间值不会发生变化的数据。 特点与变量相对常量值在定义后不可修改。 分类依据基于基本数据类型进行分类。
基本数据类型常量 基础依托于基本数据类型整型、浮点型等的常量表示。 赋值规范不同数据类型对应的常量值有特定书写格式要求。 重要性是编程基础且使用频率极高的知识点。
1整型常量 表示方法 十进制直接书写数字如 123。 八进制以 0 开头如 0123表示十进制 83。 十六进制以 0x 开头如 0x1A表示十进制 26。
2浮点型常量 标准形式必须包含小数点或指数如 3.14 或 3e53×10⁵。 科学计数法应写作 1.23e41.23×10⁴。 默认类型未加后缀默认为 double 类型加 f 后缀为 float如 3.14f。
标识常量宏定义 别称也称为宏定义#define。 作用用标识符代表常量值提高代码可读性。 语法格式#define 标识符 常量值如 #define PI 3.14159。 预处理特性在编译前进行文本替换不占用内存。
1使用规范 命名约定通常使用全大写字母如 #define MAX 100。 作用范围从定义处开始到文件结束。 类型安全宏定义不进行类型检查仅做纯文本替换。
2优势与局限 优势 便于集中修改常量值如修改 PI 精度只需改定义处。 避免 “魔法数字”直接写 3.14 等无意义数值提高代码可维护性。 局限 不占用内存空间无存储地址调试时无法查看值。 替换可能引发逻辑错误如 #define TWO 11TWO*2 会被替换为 11*23需加括号 #define TWO (11)。
基本数据类型的常量补充细节
1整型常量 进制表示细节 八进制前缀 0 和十六进制前缀 0x 不可省略如 077 是八进制 630x77 是十六进制 119。 二进制转换关系1 个八进制数对应 3 位二进制1 个十六进制数对应 4 位二进制如 0xF 对应 1111。 注意C 语言不支持直接写二进制常量需用 0b 前缀的编译器扩展非标准。
2浮点常量 精度分类 单精度float占 4 字节精度约 6-7 位小数。 双精度double占 8 字节精度约 15-17 位小数默认类型。 指数形式规则尾数可省略整数 / 小数部分如 .5e3 等价 0.5×10³5.e-2 等价 5.0×10⁻²。
3指数常量 结构组成尾数 e/E 指数如 1.23e-4 表示 1.23×10⁻⁴。 应用场景 特别大的数如地球质量 5.97e24 千克。 特别小的数如电子电荷量 1.602e-19 库仑。 优势避免书写大量零表达更简洁0.0000000035 可写为 3.5e-9。
4字符常量 定义由单引号括起的单个字符如 A、0、。 本质存储的是对应 ASCII 码值如 A 实际存储 650 存储 48。 表示方式 直接写字符aASCII 码 97。 用 ASCII 码值97等价于 a。 运算特性 可参与整数运算实际是对 ASCII 码值运算例如 大写转小写A 32 a65 32 97。 字符数字转数值5 - 48 553 - 48 5。
5字符串常量 定义用双引号括起的字符序列如 Hello、123。 存储特点自动以 \0空字符ASCII 码 0结尾例如 a 实际存储 a 和 \0共 2 字节。 与字符常量的区别 类型表示符号存储内容示例对比字符常量单引号单个字符1 字节a 占 1 字节字符串常量双引号字符序列 \0a 占 2 字节a\0
应用案例精选
例题字符常量运算
#include stdio.h
int main() {char c1 B 3; // B(66) 3 69 → Echar c2 b - 32; // b(98) - 32 66 → Bint num 9 - 0; // 9(57) - 0(48) 9printf(%c %c %d\n, c1, c2, num); // 输出E B 9return 0;
}
例题宏定义的文本替换
#include stdio.h
#define ONE 1
#define TWO ONE ONE // 注意未加括号
int main() {int a 2;int res TWO * a; // 替换为 1 1 * 2 → 3非预期的 4printf(%d\n, res);return 0;
}
// 修正#define TWO (ONE ONE)则 res (11)*2 4
知识小结
知识点核心内容考试重点 / 易混淆点难度系数基本数据类型常量整型十进制 / 八进制 / 十六进制、浮点型常规 / 科学计数法八进制以 0 开头、十六进制以 0x 开头科学计数法中 e 代表 10 的幂★★☆☆☆字符常量单引号表示ASCII 码转换大小写差 32数字字符转数值差 480ASCII 48≠ 0数值大写转小写需加 32而非直接改字母★★★☆☆字符串常量双引号表示隐含 \0 结尾a 占 2 字节含 \0与 a1 字节的区别★★★☆☆标识常量宏#define 定义预处理文本替换宏展开不做运算需加括号避免歧义无类型检查可能引发隐蔽错误★★★★☆常量综合应用科学计数法表示极值、宏定义提高可维护性如水分子数量计算浮点数精度问题宏替换后的运算符 Day02→嵌入式开发变量一
作业讲解 作业要求编写程序计算指定夸脱水中的水分子数量。 解题思路 使用宏定义常量水分子质量如 3.0e-23g和 1 夸脱质量950g。 计算公式总水分子数 (夸脱数 n × 950) / 水分子质量。 使用浮点数类型float存储变量。 输出采用科学计数法格式%e。 实现要点 需处理极小值水分子质量和极大值计算结果的数值范围。 注意 scanf 读取浮点数时应使用 %f 格式而非 %d。
变量的基础
1变量的概念 命名规则 组成字母、数字、下划线。 限制不能以数字开头不能与关键字重名如 int、if 等。 本质程序中的存储空间抽象用于存放可变化的数据。 地址特性变量首地址可通过 运算符获取如 num 表示变量 num 的地址。
2变量的存储空间 空间分配 大小由数据类型决定如 int 占 4 字节char 占 1 字节与变量值无关。 运行时实际占用内存空间空间大小可通过 sizeof(变量名) 查看。 地址特性变量首地址可通过 运算符获取用于指针操作等场景。
变量的说明 标准形式存储类型 数据类型 变量名 示例auto int age;、static float score; 存储类型auto、register、static、extern决定变量的存储方式和生命周期。 数据类型基本类型如 int、float或自定义类型如结构体、数组。 默认情况存储类型 auto 可省略如 int a; 等价于 auto int a;。
变量的存储类型
1auto 属性局部变量默认存储类型。 作用范围限定在函数体或复合语句块如 if、for 块内。 生命周期进入作用域时创建离开作用域时自动销毁。 默认值未初始化时为随机值需手动初始化后使用。 应用案例auto 变量使用示例 #include stdio.h
int main() {int a 10; // 省略auto默认是auto变量if (a 5) {auto int b 20; // 块内auto变量printf(b %d\n, b); // 输出20}// printf(b %d\n, b); // 错误b在if块外不可访问return 0;
} 注意事项 局部变量作用域严格受限跨作用域访问会报错。 使用前必须初始化否则可能读取到随机垃圾值。
2register 设计目的建议编译器将频繁访问的变量存储在 CPU 寄存器中以加速访问寄存器访问速度远快于内存。 硬件限制 寄存器数量有限32 位 CPU 通常仅几十个。 数据长度限制32 位 CPU 最大支持 4 字节64 位 CPU 最大支持 8 字节。 实现机制 编译器可忽略该建议若寄存器不足或变量不适合存寄存器自动转为 auto 类型。 使用注意事项 类型限制必须是 CPU 可直接处理的类型如 int、char长度不超过整型通常 4 字节。 操作限制不能使用 取地址寄存器无内存地址无法通过指针访问。 性能考量过度使用可能导致寄存器资源紧张反而降低性能仅适用于高频访问的小型变量如循环计数器。 示例 #include stdio.h
int main() {register int i; // 建议将i存入寄存器适合循环计数for (i 0; i 1000000; i) {// 频繁使用i寄存器存储可加速循环}// i; // 错误不能对register变量取地址return 0;
}
总结与思考
1内容总结 核心知识点 变量命名规范与存储原理大小由类型决定占据实际内存。 auto 和 register 存储类型的特性作用域、生命周期、使用场景。 关键区别 auto常规局部变量自动内存管理作用域限于代码块。 register建议放入寄存器的优化变量适用于高频访问的小型数据不可取地址。 实践要点 注意变量作用域和生命周期避免跨作用域访问错误。 合理使用 register 优化关键变量如循环计数器但避免过度使用。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数变量基础概念变量是程序中的存储空间抽象占据内存空间大小由数据类型决定变量名规则字母 / 数字 / 下划线组成不能以数字开头与关键字重名错误⭐⭐auto 存储类型默认存储类型局部变量作用域限定在代码块内未初始化时值为随机数作用域外无法访问编译报错⭐⭐⭐register 存储类型建议编译器将变量存储在 CPU 寄存器中无法取地址仅适用于频繁访问的小型数据≤4 字节实际可能仍存内存编译器可忽略建议⭐⭐⭐⭐宏定义应用通过 #define 定义常量如水分子质量 3.0e-23提高代码可读性宏替换是预处理阶段完成无类型检查可能引发类型不匹配问题⭐⭐科学计数法表示使用浮点数指数形式如 3.0e-23处理极小 / 极大值输出时用 %e 或 %g 格式注意浮点数精度损失问题⭐⭐变量作用域演示 if 代码块内变量在外部不可访问块作用域{} 内与函数作用域的区别局部变量与全局变量的作用域差异⭐⭐⭐数据类型选择示例中使用 float 处理可能的大数值结果浮点型精度有限与整型无小数的精度取舍根据数值范围选择合适类型 Day02→嵌入式开发变量二
static 存储类型
定义与特性 定义static 变量称为静态存储类型变量可在函数体内局部或函数体外全局声明。 默认值未初始化时默认值为 0与全局变量一致区别于 auto 变量的随机值。 作用范围 修饰局部变量延长生命周期至程序结束但作用域仍限于原代码块。 修饰全局变量限制作用域为当前文件其他文件无法访问。
1static 局部变量示例
代码对比
// 普通局部变量auto
#include stdio.h
void func() {int a 0; // 每次调用重新初始化a;printf(%d , a);
}
int main() {for (int i 0; i 4; i) {func(); // 输出1 1 1 1}return 0;
} // static局部变量
#include stdio.h
void func() {static int a 0; // 仅初始化一次保留上次值a;printf(%d , a);
}
int main() {for (int i 0; i 4; i) {func(); // 输出1 2 3 4}return 0;
}
关键现象 未显式初始化时static 变量默认从 0 开始如上述示例输出 1 2 3 4。 显式初始化后从初始值累加如 static int a 5则输出 6 7 8 9。
2static 局部变量的特点 存储方式存于全局数据区固定地址而非栈内存区别于 auto 变量。 生命周期从程序启动到结束持续存在不随代码块销毁。 调用特性 仅在第一次进入作用域时初始化后续调用不再重新声明。 保留上次调用的结果如累加器、计数器场景。 与 auto 的区别 特性auto 局部变量static 局部变量默认值随机值0存储位置栈内存全局数据区生命周期随代码块销毁程序全程存在初始化时机每次进入作用域仅第一次进入作用域
extern 存储类型
定义与使用条件 定义extern 称为外部引用类型用于引用其他文件中定义的全局变量声明而非定义。 使用条件 被引用变量必须是全局变量在函数体外定义。 编译时需将多个文件联合编译否则无法找到变量定义。 语法格式extern 数据类型 变量名;如 extern int global_num;。
1extern 全局变量示例
典型错误 未声明 extern 直接使用编译报错 undeclared identifier。 未联合编译即使声明 extern链接时仍报错 undefined reference。
正确用法 文件 1定义全局变量file1.c int global_a 100; // 全局变量定义仅一次 文件 2引用全局变量file2.c #include stdio.h
extern int global_a; // 声明外部变量非定义
int main() {printf(global_a %d\n, global_a); // 使用外部变量return 0;
} 联合编译 gcc file1.c file2.c -o main # 链接两个文件
./main # 输出global_a 100
2总结与思考 static 修饰全局变量的效果将全局变量的作用域限制为当前文件其他文件即使使用 extern 也无法访问实现 “文件级封装”。 extern 与 static 的关系 extern 可引用普通全局变量未被 static 修饰。 extern 无法引用static 全局变量受限于作用域。 四种存储类型对比 存储类型核心特性典型应用场景auto局部变量栈内存自动销毁函数内临时变量register建议存寄存器无地址加速访问循环计数器、高频访问变量static局部延长生命周期全局限制作用域累加器、文件内部全局变量extern跨文件引用全局变量声明而非定义多文件共享全局数据
知识小结
知识点核心内容考试重点 / 易混淆点难度系数static 修饰局部变量1. 默认初始化为 02. 生命周期延长至程序结束3. 作用域不变与 auto 的区别默认值0 vs 随机、生命周期程序全程 vs 代码块内⭐⭐⭐static 修饰全局变量限制全局变量仅在当前文件可见禁止跨文件访问与普通全局变量的对比普通可跨文件访问static 仅当前文件可见⭐⭐extern 关键字声明外部全局变量需联合编译多个文件常见错误未声明 extern、未联合编译与 static 全局变量的冲突⭐⭐⭐⭐存储类型对比auto栈、static全局区、extern跨文件、register寄存器生命周期维度auto static extern作用域维度static 全局 普通全局⭐⭐⭐⭐实验验证案例static 局部变量累加、多文件 extern 引用、static 全局变量限制访问static 局部变量的 “初始化仅一次” 特性extern 的 “声明而非定义” 本质 Day02→运算符1
算术运算符
1C 语言提供的算术运算符 运算符类型包括 加、-减、*乘、/除、%取余、自增、--自减。 书写规范 乘法符号编程中使用 * 代替数学中的 ×。 除法符号使用左斜杠 / 代替数学中的 ÷。 运算符间距建议运算符两边加空格如 a b提高代码可读性。 特殊限制 取余运算仅适用于整型数据float/double 等浮点类型不能进行取余运算。 双目运算符加减乘除取余都需要两个运算量如 a b。 单目运算符自增自减为单目运算符如 i、--j。
例题整数加减乘除运算 示例变量设 a 10b 3。 运算结果 加法a b 13 减法a - b 7 乘法a * b 30 除法a / b 3整数除法取商舍弃小数 取余a % b 1取余数 输出格式使用 %d 格式化输出整型结果如 printf(%d, a b)。
例题double 类型运算 示例变量设 x 10.0y 3.0。 运算特点 浮点除法x / y 3.333333保留小数部分。 取余限制浮点数不能使用 % 运算符会导致编译错误如 x % y 报错。 输出格式使用 %f 或 %lf 格式化输出浮点结果如 printf(%.2f, x / y)。 错误处理需要注释掉浮点取余的代码才能通过编译。
关系运算符
1C 语言的关系运算符 运算符类型包括 大于、大于等于、小于、小于等于、等于、!不等于。 书写规范 等于判断必须使用双等号 与赋值运算符 严格区分如 a 5 是判断a 5 是赋值。 不等判断使用 ! 组合表示如 a ! 0 表示 “a 不等于 0”。 运算结果返回逻辑值1 表示真0 表示假。
例题关系运算符运算 示例变量设 a 5b 10。 运算分析 a b → 5 10 → 0假 a b → 5 10 → 0假 a b → 5 10 → 1真 a b → 5 10 → 1真 a b → 5 10 → 0假 a ! b → 5 ! 10 → 1真 应用场景主要用于条件判断语句如 if和循环条件如 while。
逻辑运算符
1逻辑非 ! 运算符的运算律 基本运算包含逻辑反非 !、逻辑与、逻辑或||三种运算符。 运算规律 逻辑非对运算量取反真 变 假假 变 真。 运算示例 !a判断 a 不等于 0若 a 非 0则 !a 为 0若 a 为 0则 !a 为 1。 a 0 a 100判断 a 在 0 到 100 之间。 a 10 || b 10判断 a 或 b 小于 10。
例题逻辑非运算符使用 运算规则 当运算量为 真非 0时结果为 0假。 当运算量为 假0时结果为 1真。 代码示例 int a 5;
printf(%d\n, !a); // 输出0a非0!a为假
int b 0;
printf(%d\n, !b); // 输出1b为0!b为真 注意事项 通常会对整个表达式加括号来明确优先级例如!(a b) 是对 a b 整体取反。
2逻辑与 运算符的运算规律 运算规则 只有左右运算量都为 真非 0时结果才为 1真。 其他情况结果均为 0假。 短路特性 从左到右依次处理当左运算量为 假0时右运算量不执行逢 0 截止。 示例分析 int a 0, b 5;
int res (a ! 0) (b); // 左为假右不执行b仍为5
printf(%d %d\n, res, b); // 输出0 5
例题if 条件语句逻辑与运算 题目解析 当 (a 0) (b 0) 成立时才会执行 printf。 若 a -1则整个表达式为假printf 不会执行。 易错点 注意短路特性可能导致某些表达式不被执行如上述示例中 b 未执行。 变量初始化和使用顺序要明确。
3逻辑或 || 运算符的运算规律 运算规则 只要有一个运算量为 真非 0结果就为 1真。 只有两个都为 假0时结果才为 0假。 短路特性 从左到右依次处理当左运算量为 真非 0时右运算量不执行逢 1 截止。
例题逻辑或运算符使用 题目解析 int a 5, b 10;
int res (a 0) || (b); // 左为真右不执行b仍为10
printf(%d %d\n, res, b); // 输出1 10 注意事项 与逻辑与相反逻辑或是 “见 1 就停”。 注意区分 ||逻辑或和 |位或运算符的区别。
运算符总结
1. 算术运算符 基本运算包含加减乘除、-、*、/和取模运算%。 浮点型注意对 float/double 类型无需特殊处理直接使用基本运算符即可但不支持 %。
2. 关系运算符 比较运算包含小于、小于等于、大于、大于等于、相等、不等!等。 结果特性返回布尔值0 或 1用于条件判断。
3. 逻辑运算符 短路特性逻辑与是 “逢零截止”逻辑或||是 “逢一截止”。 执行特点部分表达式可能因短路特性而不会被执行。 使用注意 逻辑与当第一个操作数为假时第二个操作数不会执行。 逻辑或当第一个操作数为真时第二个操作数不会执行。
4. 例题逻辑运算求值 题目解析 设 x 5 y 18 示例 1x 0 y 20 → 结果为 1x5 满足y18 满足。 示例 2x 0 y 10 → 结果为 0y18 不满足。 示例 3x 0 y 20 → 结果为 0x5 不满足。 示例 4x 0 || y 10 → 结果为 1x5 满足第一个条件。 示例 5x 0 || y 20 → 结果为 1y18 满足第二个条件。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数算术运算符加减乘除、取余%操作float/double 不支持取余运算取余运算仅限整数乘法用 * 代替 ×除法用 / 代替 ÷⭐⭐关系运算符大小比较, , , 、相等与不等!双等号 与赋值 的区别表达式结果为 0假或 1真⭐⭐逻辑运算符逻辑与、逻辑或、逻辑非!短路特性逻辑与逢 0 截止逻辑或逢 1 截止未执行的表达式可能影响变量值⭐⭐⭐运算符优先级与规范空格规范如 a b、括号明确优先级/-- 的前后置差异复杂表达式建议用括号分组⭐⭐数据类型与运算限制int 支持完整算术运算float/double 禁用取余float 除法精度问题混合类型运算的隐式转换⭐⭐⭐代码实践示例演示整形 / 浮点运算差异逻辑运算短路验证如 b 未执行案例if 条件中的副作用如 Day02→运算符2
位运算符基础
1C 语言的位运算符 运算基础位运算以二进制为基础需熟练掌握进制转换和原码 / 反码 / 补码知识。 效率优势比算术运算符效率更高在嵌入式开发中常用于精准控制硬件寄存器如设置特定引脚电平。
位逻辑反运算符~ 符号表示~单目运算符。 运算规则按位取反0 变 11 变 0。 无符号数处理直接对全部位取反不考虑符号位因无符号数无符号位。 例题字符取反计算 示例分析 定义 unsigned char x 0x17二进制 00010111取反后 ~x 得到 11101000十六进制 0xE8。 验证方法将十六进制每位转 4 位二进制后整体取反如 0x17 拆分为 0001 和 0111取反后为 1110 和 1000组合为 0xE8。 打印技巧使用 printf(%#x, y) 可自动添加 0x 前缀如输出 0xe8。
位逻辑与运算符 符号表示双目运算符。 运算规则两位都为 1 时结果为 1否则为 0即 “全 1 则 1有 0 则 0”。 清零技巧用 0 与任何位相与可实现该位清零如 a 0xFE 可清零最低位。 应用场景嵌入式开发中精准控制寄存器特定位如读取某引脚状态时屏蔽其他位。 例题字符与运算 示例分析 设 a 056八进制二进制 01010110b 0xac十六进制二进制 10101100则 a b 结果为 00000100十六进制 0x04。 验证要点按位比对只有第 3 位从 0 开始计数同时为 1故结果对应位为 1。
位逻辑或运算符| 符号表示|双目运算符。 运算规则两位有 1 时结果为 1全 0 时才为 0即 “有 1 则 1全 0 则 0”。 置位技巧用 1 或任何位可实现该位置 1如 a | 0x01 可将最低位置 1。 例题字符或运算 示例分析 设 a 036八进制二进制 00111110b 0x89十六进制二进制 10001001则 a | b 结果为 10111111十六进制 0xBF。 计算技巧逐位观察只要两位中至少有 1则结果位为 1。
位逻辑异或运算符^ 符号表示^双目运算符。 运算规则两位相异为 1相同为 0即 “同 0 异 1”。 特殊性质 一个数异或自己结果为 0a ^ a 0。 一个数异或 0 保持原值a ^ 0 a。 例题字符异或运算 示例分析 设 a 75十进制二进制 01001011b 0173八进制二进制 01111011则 a ^ b 结果为 00110000十六进制 0x30 或八进制 060。 记忆口诀“同 0 异 1” 可快速判断异或结果。
2位移位运算
移位运算的一般形式 基本语法运算量 运算符 整型表达式如 a 3表示 a 左移 3 位。 运算符类型 左移 高位丢弃低位补 0。 右移 低位丢弃高位补符号位有符号数或 0无符号数。 注意事项运算量和表达式都必须是整型数据类型char、int、long 等。
位运算与移位操作
1. 十六进制与二进制转换 转换方法十六进制的每一位对应 4 位二进制如 0x4 对应 01000xE 对应 11100xF 对应 1111。 补位规则当二进制位数不足时在前面补零使其达到数据类型要求的位数如 unsigned char 为 8 位0x4 补位后为 00000100。
2. 左移运算原理 操作定义a 3 表示将变量 a 的二进制位左移 3 位右边空出的位补 0。 位移特性 左移一位相当于乘以 2左移 n 位相当于乘以 2ⁿ无溢出情况下。 移出的高位直接丢弃低位补零。 对于无符号数如 unsigned char最高位移出不会产生符号问题因无符号位。 实例演示0xE4二进制 11100100左移 3 位后高位 3 位丢弃低位补 3 个 0得到 00100000十六进制 0x20。
3. 例题验证左移运算 题目解析 代码实现 #include stdio.h
int main() {unsigned char x 0xe4; // 二进制 11100100unsigned char y x 3;printf(y %#x\n, y); // 输出 y 0x20return 0;
} 运行结果验证得到 y 0x20与理论计算结果一致。 易错点需注意数据类型是否为无符号数有符号数的左移可能因符号位变化导致结果异常如溢出后变为负数。
4. 移位运算的数学本质 数学规律 左移 1 位相当于乘以 2a 1 a * 2。 左移 2 位相当于乘以 4a 2 a * 4。 左移 3 位相当于乘以 8a 3 a * 8。 二进制演示 以 0x04 为例 初始值000001004。 左移 1 位000010008 4 * 2。 左移 2 位0001000016 4 * 4。 左移 3 位0010000032 4 * 8。 记忆口诀“左移乘二右移除二”可快速计算移位结果无溢出时。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数位运算符基础位运算以二进制为基础与逻辑运算的区别无符号数处理规则进制转换16 进制 / 8 进制 / 二进制取反操作对无符号数的影响⭐⭐位运算类型逻辑与、逻辑或、取反~、异或^的运算规则及示例异或运算 “同 0 异 1” 特性与 / 或运算的清零 / 置位技巧⭐⭐⭐移位运算左移与右移操作左移等价于乘 2 的幂次方移位后补位规则左移补 0右移区分有符号 / 无符号无符号数移位与符号位问题⭐⭐位运算应用场景提高程序效率优于加减乘除嵌入式开发中寄存器精准控制硬件寄存器操作中的位掩码设计如用 读取特定位用 设置特定位⭐⭐⭐⭐实践验证方法通过代码示例验证位运算结果强调手动计算与程序输出对比16 进制 / 二进制转换的准确性移位运算中的溢出问题⭐⭐易错点总结混淆逻辑运算符/
Day02→运算符3
位运算的核心应用与例题解析
1. 思考 基本运算符包括位逻辑反~、位逻辑与、位逻辑或|、位逻辑异或^、位逻辑移位 和 。 核心应用通过位运算可以精准控制数据的特定位如设置为 1、清零、翻转等在硬件寄存器操作中尤为重要例如控制 GPIO 引脚电平、配置外设功能等。
2. 例题无符号数置 1 实现原理 利用位逻辑或| 的特性1 与任何位进行或运算结果必为 10 与任何位进行或运算保持原值。通过构造 “目标位为 1其余位为 0” 的掩码与原数进行或运算即可将目标位置 1。 掩码构造 将 1 左移 (y-1) 位生成仅目标位为 1 的掩码如 y2 时1 1 00000010掩码为 0x02。 代码实现 #include stdio.h
int main() {unsigned char x 0x04; // 二进制 0100int y 2; // 目标位从1开始计数x x | (1 (y - 1)); // 第2位置1掩码为 00000010printf(0x%x\n, x); // 输出 0x6二进制 0110return 0;
} 验证过程0x40100的第 2 位置 1 后变为 0x60110符合预期。
3. 例题无符号数清 0 实现原理 利用位逻辑与 的特性0 与任何位进行与运算结果必为 01 与任何位进行与运算保持原值。通过构造 “目标位为 0其余位为 1” 的掩码与原数进行与运算即可将目标位清零。 掩码构造 先构造目标位为 1 的掩码1 (y-1)再对其取反~得到目标位为 0、其余位为 1 的掩码如 y3 时~(1 2) ~00000100 11111011。 代码实现 #include stdio.h
int main() {unsigned char x 0x14; // 二进制 00010100int y 3; // 目标位从1开始计数x x ~(1 (y - 1)); // 第3位清零掩码为 11111011printf(0x%x\n, x); // 输出 0x10二进制 00010000return 0;
} 验证过程0x1400010100的第 3 位从右数清零后变为 0x1000010000目标位成功清零。
4. 例题十进制转十六进制位运算优化 数学原理 十六进制的每位对应 4 位二进制因此可用位运算替代除法和取余 取整替代a / 16 等价于 a 4右移 4 位丢弃低 4 位相当于除以 16。 取余替代a % 16 等价于 a 0xF与 0xF二进制 1111运算保留低 4 位即余数。 代码对比 #include stdio.h
int main() {int a 65;// 常规方法int quotient1 a / 16; // 商为4int remainder1 a % 16; // 余为1// 位运算方法int quotient2 a 4; // 右移4位商为4int remainder2 a 0xF; // 与0xF余为1printf(常规商%d 余%d\n, quotient1, remainder1);printf(位运算商%d 余%d\n, quotient2, remainder2);return 0;
} 验证过程65十六进制 0x41转换后商为 4、余为 1两种方法结果一致位运算更高效。
位运算的应用价值与学习建议
应用价值
位运算在底层开发如嵌入式、驱动开发中具有高效直接操作二进制无需复杂运算、精准可单独控制某一位的优势特别适合硬件寄存器操作如配置外设、读写状态位等。
学习建议 反复练习掩码构造如何生成目标位的掩码和位操作技巧置 1、清零、翻转、提取位等。 掌握位运算与常规运算的等价转换如右移替代除法、与运算替代取余理解其效率优势。 结合硬件场景练习如模拟寄存器配置加深对 “位级控制” 的理解。
知识小结
知识点核心内容考试重点 / 易混淆点难度系数位运算基础逻辑与、逻辑或、异或^、位移/的操作规则位运算与逻辑运算的区别移位方向与结果的关系⭐⭐位操作应用无符号数特定位操作置 1 / 清零利用掩码实现精准控制或运算置1与与运算清零的区别掩码构造的逻辑⭐⭐⭐置 1 操作实现x x(1 (y-1))如 0x4 第 2 位置 1→0x6左移位数与目标位的对应关系y-1 的计算逻辑⭐⭐清零操作实现x x ~(1 (y-1))如 0x14 第 3 位清零→0x10取反操作~的优先级掩码取反后的位分布⭐⭐⭐进制转换十进制转十六进制右移 4 位替代 ÷16与 0xF 替代 %16位运算替代数学运算的原理0xF 的作用保留低 4 位⭐⭐⭐⭐硬件寄存器控制位运算精准控制硬件寄存器特定位如配置 GPIO、外设功能实际应用中掩码的设计如何覆盖目标位多比特位同时操作的技巧
Day02→运算符4
赋值运算符
1基本赋值运算符 基本形式如 int a 5; 执行特点将右值表达式的计算结果赋给左值变量左值必须是可修改的变量不能是常量或表达式。 常见误区编程中的 表示赋值而非数学中的 “相等” 关系判断相等用 。
2赋值复合运算符 简化原理a b 等价于 a a b其他运算符同理。 运算符类型 算术类、-、*、/、% 位运算类、|、^、、 使用优势简化代码书写减少变量重复书写部分编译器可优化执行效率。
例题赋值复合运算符应用
#include stdio.h
int main() {int sum 0, count 1;while (count 20) { // 先判断后自增累加到20sum count; // 等价于 sum sum count}printf(sum %d\n, sum); // 输出2101到20的累加和return 0;
} 代码解析 sum count 简化了累加操作循环变量 count 初始化为 1通过自增控制循环次数。 计算结果为 1 到 20 的累加和210验证了复合运算符的实用性。
特殊运算符
1条件运算符三目运算符 语法结构表达式1 ? 表达式2 : 表达式3 执行逻辑 先计算表达式 1 若为真非 0整个表达式取表达式 2 的值 若为假0取表达式 3 的值。 等价关系相当于简化的 if-else 结构如 a b ? a : b 等价于 if(a b) return a; else return b;。
例题三目运算符应用
#include stdio.h
int main() {int score 82;// 成绩分级≥101→10090-100→9090→60int res (score 101) ? 100 : (score 90 ? 60 : 90);printf(res %d\n, res); // 输出608290取60return 0;
} 变量分析 score 82score 101 不成立 → 进入第二个三目运算 score 90 成立 → 取 60最终结果为 60。
例题三目运算符与自增结合
#include stdio.h
int main() {int x 70, y;// 版本1先比较后自增x 80 中x先取值70再自增为71y (x 80) ? 100 : 0; printf(版本1x%d, y%d\n, x, y); // 输出71, 0x 70; // 重置x// 版本2先自增后比较x 80 中x先自增为71再比较y (x 80) ? 100 : 81; printf(版本2x%d, y%d\n, x, y); // 输出71, 81return 0;
} 关键点区分 x先取值后自增和 x先自增后取值的执行时机直接影响结果。
2逗号运算符 语法特点用括号包含多个表达式以逗号分隔如 (表达式1, 表达式2, ..., 表达式n)。 执行规则 从左到右依次执行各个表达式 整个表达式的值为最后一个表达式的值。 典型应用 多变量初始化int a 1, b 2, c 3; 复合运算for (i0, j10; ij; i, j--)。
例题逗号运算符应用
#include stdio.h
int main() {float x 5.5, y 1.8;float res (x * 3, y 1.0, x y); // 逗号表达式// 执行步骤// 1. x * 3 → x 16.5// 2. y 1.0 → y 2.8// 3. 取最后一个表达式 x y → 19.3printf(res %.1f\n, res); // 输出19.3可能有浮点精度误差return 0;
}
3sizeof 运算符 功能作用计算数据类型或变量所占内存的字节数。 使用形式 类型sizeof(数据类型)如 sizeof(int) 变量sizeof(变量名) 或 sizeof 变量名如 sizeof(a) 或 sizeof a。 32 位系统典型值 int4 字节long4 字节long long8 字节char1 字节。 注意事项结果由数据类型决定与变量的具体值无关如 int a 0; sizeof(a) 仍为 4 字节。
运算符的优先级
1优先级表核心规则 优先级规则表中优先级从上到下依次降低数值越小优先级越高如 1 为最高15 为最低。 常见运算符优先级从高到低 括号()、方括号[] 单目运算符!、~、、--、sizeof 算术运算符*、/、% 高于 、- 位运算符、 高于 、^、| 关系运算符、、、 高于 、! 逻辑运算符 高于 || 三目运算符?: 赋值运算符、、- 等 逗号运算符,。 易混淆点 赋值运算符优先级低于逻辑判断运算符 逻辑与优先级高于逻辑或||。 记忆技巧 括号优先级最高可强制改变运算顺序 复杂表达式建议用括号明确顺序如 (a b) * c 比 a b * c 更清晰。
例题运算符优先级应用
#include stdio.h
int main() {int x 1, y 0, z 0;// 逻辑与优先级高于逻辑或||int result x y || z;// 执行顺序// 1. x y → x先取值1后自增为2y先取值0后自增为1逻辑与结果为0// 2. 0 || z → 计算zz变为1逻辑或结果为1printf(result %d, x%d, y%d, z%d\n, result, x, y, z);// 输出result1, x2, y1, z1return 0;
}
知识小结
知识点核心内容考试重点 / 易混淆点难度系数复合赋值运算符、-、* 等简化写法如 a b 等价于 a a b自增 / 自减与复合运算的结合如 count 20 先判断后自增⭐⭐三目运算符表达式1 ? 表达式2 : 表达式3等价于简化的 if-else执行顺序先判断表达式 1再选择表达式 2/3与自增结合时的执行时机⭐⭐⭐逗号运算符多个表达式从左到右执行结果为最后一个表达式的值优先级最低与赋值或逻辑运算结合时需加括号如 (a1, b2, ab)⭐⭐⭐⭐sizeof 运算符计算变量或类型的内存字节数如 sizeof(int)结果由类型决定与变量值无关区分 sizeof(a) 和 sizeof(a[0])数组场景⭐运算符优先级括号 算术 关系 逻辑 赋值 逗号 优先级高于 如 if(x y 1) 易出错逻辑与优先级高于逻辑或⭐⭐⭐⭐短路特性逻辑与逢 0 截止逻辑或逢 1 截止结合优先级分析短路条件如 x yz 中逻辑与优先执行⭐⭐⭐自增 / 自减陷阱x先取值后自增与 x先自增后取值的区别复合表达式中影响结果如三目运算符、逻辑判断中的自增时机