C语言运算符与表达式完全指南:从入门到精通,这一篇就够了

📅 2026/8/4 5:22:08
C语言运算符与表达式完全指南:从入门到精通,这一篇就够了
摘要运算符是C语言的动词表达式是C语言的句子。本文系统讲解C语言中的语句分类、表达式概念、全部运算符的用法与注意事项涵盖算术运算、赋值运算、位运算、逻辑运算、比较运算、类型转换、优先级等核心知识点。文章附带大量代码示例和实战技巧适合初学者系统学习也适合作为随时查阅的参考手册。正文1. 语句C程序的基本执行单元C语言的程序主体由函数构成而函数体由语句组成。1.1 语句的分类┌─────────────────────┐ │ C语言语句 │ └──────────┬──────────┘ │ ┌──────────────────┴──────────────────┐ │ │ ┌───▼───┐ ┌───────▼───────┐ │执行语句│ │ 非执行语句 │ │ 被编译 │ │ 不被编译 │ │成机器码│ │ 编译期生效 │ └───┬───┘ └───────────────┘ │ ┌───────┼───────────────┬───────────────┐ │ │ │ │ ┌───▼───┐ ┌─▼───┐ ┌───────▼───────┐ ┌─────▼─────┐ │复合语句│ │单条 │ │ 表达式语句 │ │ 跳转语句 │ │{...} │ │语句 │ │ a b c; │ │ return │ └───────┘ └─────┘ └───────────────┘ └───────────┘执行语句的主要分类类型形式示例复合语句{ 语句1; 语句2; ... }{ int a; a 5; }变量定义语句Type 变量名;int age 25;函数调用语句函数名(参数);printf(Hello\n);表达式语句表达式;a b c;跳转语句return/break/continue/gotoreturn 0;空语句;什么也不做占位用空语句的使用场景循环体为空时如while(*dst *src);2. 表达式有计算结果的式子表达式是由常量、变量、运算符和子表达式组成的、具有计算结果的式子。判断标准有运算结果的就是表达式。2.1 表达式的三种类型类型运算结果示例数值表达式具体数值3 5→ 8逻辑表达式真(非0) 或 假(0)3 5→ 真(1)地址表达式内存地址值x、ptr 12.2 表达式的基本组成单独常量也是表达式3→ 结果为3单独变量也是表达式x→ 结果为x的当前值子表达式可以嵌套(a b) * c中a b是子表达式开发建议不鼓励写太复杂的表达式影响可读性。多拆几行多用中间变量。3. 运算符概览3.1 按操作数个数分类类型操作数个数示例运算符单目运算符一元1个、*、、--、!、~、-双目运算符二元2个、-、*、/、%、、、||三目运算符三元3个?:唯一3.2 按功能分类类别运算符算术运算符-*/%赋值运算符-*/%|^自增自减--位运算符|^~比较运算符!逻辑运算符||!地址运算符条件运算符?:逗号运算符,强制类型转换(Type)sizeof运算符sizeof4. 针对变量的基本运算4.1 取地址运算符单目用法变量名功能获取变量的内存首地址示例int x 10; printf(%p, x); // 输出0x7ffc123456784.2 赋值运算符双目用法变量名 同类型表达式功能将表达式的值存入变量空间注意事项赋值号左边必须是变量或可充当变量名的写法赋值号左右类型要一致——这是C语言编程的第一原则赋值表达式本身也有值就是左侧变量最终获得的值x 2; // 这个表达式的值是2 y (x 2); // y也得到2赋值时的类型转换规则重要转换方向规则示例浮点→整型取整截断小数无四舍五入int x 3.9;→ x3整型→浮点加.0无损float f 5;→ f5.0大整型→小整型按字节截取short s 0x12345678;→ 损失高位小整型→大整型符号扩展或零扩展无损int x (short)5;double→float可能变成inf超出范围变无穷有符号→无符号负数变成大正数unsigned u -1;→ u4294967295无符号→有符号太大可能变负int x 0xFFFFFFFFu;→ x-14.3 sizeof 运算符单目三种用法sizeof(数据类型名) // 推荐sizeof(int) sizeof(变量名) // 推荐sizeof(x) sizeof(表达式) // 不推荐 sizeof 变量名 // 不推荐省略括号核心要点sizeof是编译阶段进行的运算生成的代码中直接被替换为常数结果类型是size_t即unsigned long的别名陷阱示例int a 5; int b sizeof(a); // a 不会被执行 printf(%d, a); // 输出5因为sizeof(a)在编译时直接计算出结果通常是4a的代码根本不会生成。5. 算术运算符5.1 双目算术运算符运算符功能注意事项加法可能溢出-减法可能溢出*乘法可能溢出/除法分母不能为0整数除法取整%取余仅限整型操作数分母不能为0整数除法的特殊性int a 5 / 2; // 结果2不是2.5 float b 5 / 2; // 结果2.0先整数除法得2再转float float c 5.0 / 2; // 结果2.5浮点除法防御性编程if (y ! 0) { result x / y; } else { // 处理除零情况 }5.2 单目算术运算符和--四种写法写法名称效果x前置自增x先1用新值作为表达式结果x后置自增用旧值作为表达式结果然后x1--x前置自减x先-1用新值作为表达式结果x--后置自减用旧值作为表达式结果然后x-1示例int x 6; int y; y x; // x7, y7先加后用 y x; // x7, y6先用后加⚠️ 六个重要注意事项不要在同一个语句中多次修改同一个变量int a 5; a 2 a; // 结果未定义不同编译器可能不同函数实参中不要对同一变量多次自增int a 5; printf(%d, %d\n, a, a); // 结果未定义善用括号明确运算顺序b a c; // 二义性 b a (c); // 清晰不要在sizeof中使用自增自增不会执行不要在逻辑运算的子表达式中修改变量可能因为短路而不执行不要在/||连接的后续表达式中修改变量6. 位运算符位运算对操作数的每一个二进制位逐位进行运算。只能用于整型和char型操作数。6.1 四种位逻辑运算符运算符名称规则示例按位与有0为0全1为10b1010 0b1100 0b1000|按位或有1为1全0为00b1010 | 0b1100 0b1110^按位异或相同为0不同为10b1010 ^ 0b1100 0b0110~按位取反0变11变0~0b1010 0b010132位内6.2 移位运算符运算符方向规则特殊作用左移高位舍弃低位补0无符号时左移1位×2右移低位舍弃高位补0逻辑右移或补符号位算术右移无符号时右移1位÷2⚠️ 右移的陷阱对于有符号整数右移补0还是补符号位由编译器决定这导致有符号右移是二义性的项目开发中极度不推荐使用6.3 位运算的实战技巧技巧一使用掩码Mask目标掩码操作示例某位置0x x ~mask清除第3位x ~(13)某位置1x x | mask置第3位为1x | (13)某位取反x x ^ mask翻转第3位x ^ (13)判断某位if (x mask)判断第3位if (x (13))技巧二利用规律判断一个整数是否为2的n次方if ((x (x - 1)) 0) { // x是2的n次方包括x0的情况需要额外排除 }判断奇偶if (x 1) { // 奇数 } else { // 偶数 }⚠️ 位运算的核心注意事项所有位都参与运算包括符号位尽量只对无符号类型做位操作否则结果可能出乎意料构造掩码时要考虑类型的完整位数7. 比较运算符关系运算符运算符含义示例大于a b小于a b大于等于a b小于等于a b等于a b!不等于a ! b⚠️ 三个重要注意事项和的区别写错是初学者最常犯的错误if (x 1) { // 赋值条件永远为真 // ... } if (x 1) { // 判断这才是正确的 // ... }不要连写比较表达式// 错误写法 if (3 a 0) { } // 不会按数学方式解析 // 正确写法 if (3 a a 0) { }浮点数比较是否等于0要做精度处理#include float.h float x 0.0000001; // 错误写法 if (x 0.0) { } // 正确写法 if (x 0.00001 x -0.00001) { // 认为x等于0 }防御性编程小技巧将常量写在左侧if (1 x) { // 如果不小心写成 1 x编译器会报错 // ... }8. 逻辑运算符8.1 逻辑与功能所有条件都为真结果才为真真值表有假则为假全真才为真8.2 逻辑或||功能任一条件为真结果就为真真值表有真则为真全假才为假8.3 逻辑非!功能取反真变假假变真8.4 ⚠️ 逻辑短路重要int a 9; int b 0; // 逻辑与短路b ! 0 为假整个表达式已确定为假 // 后续的 a 8 根本不会执行 if (b ! 0 a 8) { } printf(%d, a); // 输出9a没有变化核心原则不要在或||连接的后续表达式中修改变量值——因为可能因为短路而不会被执行。逻辑与/或的优先级// 逻辑与高于逻辑或 if (a || b c) // 等价于 a || (b c)9. 复合赋值运算符为了偷懒而存在的运算符本质是先运算再赋值。x 6; // 等价于 x x 6 x - 6; // 等价于 x x - 6 x * 6; // 等价于 x x * 6 x / 6; // 等价于 x x / 6 x % 6; // 等价于 x x % 6 x 6; // 等价于 x x 6 x | 6; // 等价于 x x | 6 x ^ 6; // 等价于 x x ^ 6 x 6; // 等价于 x x 6 x 6; // 等价于 x x 610. 逗号运算符用法表达式1, 表达式2, ..., 表达式n功能从左到右依次计算每个表达式整个表达式的值为最后一个表达式的值示例int a 2, b 3, c; c (a, b 4, a b); // 先 a → a3 // 再 b4 → b7 // 最后 c ab 10⚠️ 注意变量定义中的逗号int a,b,c;、函数实参中的逗号printf(%d, a);都只是分隔符不是逗号运算符。11. 条件运算符?:唯一的三目运算符用法条件表达式 ? 表达式2 : 表达式3功能条件为真 → 整个表达式值 表达式2的值条件为假 → 整个表达式值 表达式3的值示例int max (a b) ? a : b; // 取a和b中的较大值等价于if (a b) { max a; } else { max b; } 条件运算符可以嵌套但过于复杂会严重影响可读性不推荐。12. 类型转换12.1 自动类型转换场景一无赋值运算的表达式规则char和short→ 提升为intfloat→ 提升为double不同类型的操作数 → 统一提升为级别较高的类型类型级别从低到高char/short → int → unsigned int → long → unsigned long → double场景二赋值号两边的转换遵循类型一致化原则右边值的类型 → 转换为左边变量的类型转换场景结果浮点→整型取整截断小数整型→浮点加.0无损大整型→小整型按字节截取有损小整型→大整型提升无损double→float可能变成inf有符号→无符号负数变正数无符号→有符号可能变负12.2 强制类型转换用法(类型名) 表达式功能手动将表达式值转换为指定类型转换规则同赋值转换。示例int a 5, b 2; float result (float)a / b; // result 2.5而不是213. 符号运算符-可以作为单目运算符表示取相反数。int x 5; int y -x; // y -5 int z -(-x); // z 514. 运算符优先级与结合性14.1 速记口诀函数调用加括号单目成员把雄傲算术先于比大小然后逻辑才来到赋值倒数第二低逗号运算最低调单目从右向左走赋值也从右向左别人式子看着彪多加括号来分晓。14.2 核心优先级规则优先级运算符类别结合性最高()[].-后置/--左→右高单目运算符*-!~前置/--右→左中强制类型转换(Type)右→左中算术运算符*/%-左→右中移位运算符左→右中比较运算符!左→右中位逻辑运算符^|左→右中逻辑运算符||左→右中条件运算符?:右→左低赋值运算符右→左最低逗号运算符,左→右14.3 最重要的实战建议 不要死记优先级表记住两条就够了善用圆括号()明确运算顺序不要写复杂的表达式拆成多行多用中间变量// 看不懂的写法 result a b * c 2 0xFF; // 清晰的写法 temp1 b * c; temp2 (a temp1) 2; result temp2 0xFF;15. 选择语句基础15.1 单条件体形式if (表达式) { // 条件为真时执行 }15.2 双条件体形式if (表达式) { // 条件为真时执行 } else { // 条件为假时执行 }执行逻辑计算条件表达式的值真非0→ 执行真条件体假0→ 执行假条件体或什么都不做写在最后本文覆盖了C语言中所有常用的运算符和表达式知识以及语句的分类体系。这些内容看似琐碎但它们是写出正确、高效、可读的C语言程序的基本功。三个核心建议类型一致化是C语言的第一原则——赋值时、传参时、运算时尽量保持类型一致不要写聪明的代码——写清晰的代码让后来者包括未来的自己能一眼看懂善用括号——与其纠结优先级不如用括号明确表达意图如果这篇文章对你有帮助欢迎点赞、收藏、转发让更多人系统掌握C语言的运算符与表达式