你们好我是一名嵌入式工程师。我正在持续更新《嵌入式工程师的C语言实战》系列教程目前已更新4篇。如果你也在学习嵌入式欢迎点个关注我们一起从零到一。文章目录前言一、算术运算符Arithmetic Operators二、关系运算符Relational Operators三、逻辑运算符Logical Operators四、位运算符Bitwise Operators五、赋值运算符Assignment Operators六、自增自减运算符Increment/Decrement Operators七、条件运算符Conditional Operator / 三目运算符八、逗号运算符Comma Operator九、sizeof 运算符十、地址与间接访问运算符十一、成员访问运算符十二、其他运算符十三、运算符优先级速查表从高到低如果这篇文章对你有帮助欢迎点赞、收藏、关注主播是一个马上粉丝量超1个的嵌入式内容主播。谢谢前言C语言的运算符非常丰富涵盖了算术、关系、逻辑、位运算、赋值等各个领域。下面为你系统性地分类整理并附上详细的说明和示例。C语言的运算符覆盖了从基础算术到内存操作的方方面面按功能可归纳为分类运算符算术类 - * / % –比较类 !逻辑类 || !位操作类 | ^ ~ 赋值类 及其复合形式地址与访问类 * . -其他sizeof ?: , () [] (type)一、算术运算符Arithmetic Operators用于执行基本的数学运算。运算符含义示例说明加法a b两数相加-减法a - b两数相减*乘法a * b两数相乘/除法a / b两数相除整数除法会截断%取模求余a % b返回两数相除的余数仅用于整数#includestdio.hintmain(){inta10,b3;printf(10 3 %d\n,ab);// 13printf(10 - 3 %d\n,a-b);// 7printf(10 * 3 %d\n,a*b);// 30printf(10 / 3 %d\n,a/b);// 3整数除法截断printf(10 %% 3 %d\n,a%b);// 1余数return0;}二、关系运算符Relational Operators用于比较两个值的大小关系返回 1真或 0假。运算符含义示例说明大于a ba 是否大于 b小于a ba 是否小于 b大于等于a ba 是否大于等于 b小于等于a ba 是否小于等于 b等于a ba 是否等于 b注意是两个等号!不等于a ! ba 是否不等于 binta5,b5;printf(%d\n,ab);// 输出 1真printf(%d\n,ab);// 输出 0假常见错误把 写成 会导致赋值而非比较。三、逻辑运算符Logical Operators用于组合多个条件返回 1真或 0假。运算符含义示例说明逻辑与a b两个条件都为真时才为真短路求值||逻辑或a || b至少一个条件为真时为真短路求值!逻辑非!a取反真变假假变真intage20,score85;if(age18score60){printf(成年且及格\n);}if(!(age18)){printf(已成年\n);}短路求值示例intx0;if(x!010/x1){// 因为 x ! 0 为假短路不会执行 10 / x避免除零错误// ...}四、位运算符Bitwise Operators用于对整数的二进制位进行操作。运算符含义示例说明按位与a b对应位都为 1 时结果为 1|按位或a | b对应位至少一个为 1 时结果为 1^按位异或a ^ b对应位不同时为 1相同时为 0~按位取反~a所有位取反0变11变0左移a n所有位左移 n 位低位补 0右移a n所有位右移 n 位符号位取决于类型unsignedchara0b1100;// 12unsignedcharb0b1010;// 10printf(a b %d\n,ab);// 8 (0b1000)printf(a | b %d\n,a|b);// 14 (0b1110)printf(a ^ b %d\n,a^b);// 6 (0b0110)printf(~a %d\n,~a);// 243 (0b11110011)printf(a 2 %d\n,a2);// 48 (0b110000)printf(a 2 %d\n,a2);// 3 (0b0011)五、赋值运算符Assignment Operators用于给变量赋值其中复合赋值运算符结合了运算和赋值。运算符含义示例等价于简单赋值a 10a 10加后赋值a 5a a 5-减后赋值a - 5a a - 5*乘后赋值a * 5a a * 5/除后赋值a / 5a a / 5%取模后赋值a % 5a a % 5按位与后赋值a 5a a 5|按位或后赋值a | 5a a | 5^按位异或后赋值a ^ 5a a ^ 5左移后赋值a 2a a 2右移后赋值a 2a a 2intx10;x5;// x 15x*2;// x 30printf(%d\n,x);六、自增自减运算符Increment/Decrement Operators用于将变量的值增加或减少 1。运算符含义示例说明自增a 或 a变量加 1–自减a-- 或 --a变量减 1前缀 vs 后缀前缀a先自增再使用变量的值。后缀a先使用变量的值再自增。inta5;intba;// a 变为 6b 被赋值为 6intca--;// c 被赋值为 6使用 a 的当前值然后 a 变为 5printf(a%d, b%d, c%d\n,a,b,c);// a5, b6, c6七、条件运算符Conditional Operator / 三目运算符唯一的三目运算符用于简化 if-else。运算符语法说明?:条件 ? 表达式1 : 表达式2若条件为真取表达式1的值否则取表达式2的值intage20;constchar*status(age18)?成年:未成年;printf(%s\n,status);// 输出成年八、逗号运算符Comma Operator用于将多个表达式串联成一个表达式按从左到右的顺序执行整个表达式的值是最右边表达式的值。inta,b;a(b3,b2);// 先执行 b3然后执行 b25整个表达式值为 5printf(a%d, b%d\n,a,b);// a5, b3九、sizeof 运算符sizeof 是 C/C 中一个编译时的一元运算符它用于计算一个类型或变量在内存中占用的字节数。它既不是函数尽管写法像也不是关键字而是一个运算符。9.1 sizeof 的核心作用获取类型大小查询基本类型int, double或自定义类型struct, enum的存储大小。获取变量大小获取任何变量或表达式结果的大小。辅助内存分配在 malloc、calloc 或 new 时用于计算需要分配的内存大小。计算数组元素个数通过 sizeof(array) / sizeof(array[0]) 得到数组长度。9.2 sizeof 的常见用法#includestdio.hintmain(){// 1. 作用在类型上printf(int 大小: %zu\n,sizeof(int));// 通常 4printf(double 大小: %zu\n,sizeof(double));// 通常 8// 2. 作用在变量上inta10;doubled3.14;printf(变量 a 大小: %zu\n,sizeof(a));// 4printf(变量 d 大小: %zu\n,sizeofd);// 8括号可省略// 3. 计算数组长度intarr[10]{0};size_tlensizeof(arr)/sizeof(arr[0]);// 10/1 10printf(数组元素个数: %zu\n,len);// 4. 动态内存分配int*p(int*)malloc(10*sizeof(int));// 分配 10 个 int 的空间if(p)free(p);return0;}9.3 sizeof 的注意事项9.3.1 sizeof 是编译时求值sizeof 的结果在编译阶段就确定了因此它不关心括号内的内容变长数组除外。括号内是 0 还是 100对结果没有任何影响。#includestdio.hintmain(){intx10;// 这两种写法结果完全相同都是 sizeof(int)printf(sizeof(x) %zu\n,sizeof(x));// 输出 4假设 int 为 4 字节printf(sizeof(x5) %zu\n,sizeof(x5));// 输出 4表达式类型是 intreturn0;}关键点sizeof(x5) 不会计算 x5 的值它只推导出 (x5) 的类型是 int所以结果是 4。区别对待变长数组VLA是唯一的例外只有变长数组VLA 的 sizeof 是在运行时求值的。这时编译器必须知道其具体长度因此 sizeof 会“关心”括号内的内容即数组的长度表达式。#includestdio.hintmain(){intn5;intvla[n];// 变长数组VLAprintf(sizeof(vla) %zu\n,sizeof(vla));// 输出 205*4在运行时计算printf(sizeof(vla) %zu\n,sizeof(int[n]));// 输出 20也是运行时求值return0;}9.3.2 对数组和指针的区分intarr[10];int*ptrarr;printf(数组: %zu\n,sizeof(arr));// 40 (10*4)printf(指针: %zu\n,sizeof(ptr));// 8 (64位系统)结构体对齐填充sizeof 结构体返回的是包含内存对齐填充后的总大小可能大于成员大小之和。9.4 sizeof 与 strlen 的区别这是初学者最容易混淆的两个概念。sizeof 是运算符strlen 是函数它们有本质区别。特性sizeofstrlen本质运算符编译时求值函数运行时求值计算对象类型、变量、任何表达式必须以 ‘\0’ 结尾的字符串计算内容在内存中占用的总字节数字符串中 ‘\0’ 之前的字符个数是否包含结尾符包含数组或字符串字面量不包含参数要求任何类型必须是 char* 类型示例对比#includestdio.h#includestring.hintmain(){charstr[]Hello;// 实际存储: H e l l o \0printf(sizeof(str) %zu\n,sizeof(str));// 输出 6 (包含 \0)printf(strlen(str) %zu\n,strlen(str));// 输出 5 (不包含 \0)// 对指针使用 sizeof 与 strlen 的区别char*pHello;printf(sizeof(p) %zu\n,sizeof(p));// 输出 8 (指针本身大小)printf(strlen(p) %zu\n,strlen(p));// 输出 5 (字符串长度)}总结sizeof问的是“这个类型或变量在内存里占多大的空间”strlen问的是“从字符串开头到第一个 ‘\0’ 之前有多少个字符”十、地址与间接访问运算符运算符含义示例说明取地址var获取变量的内存地址*解引用间接访问*ptr访问指针指向的内存内容intx10;int*px;// p 存储 x 的地址printf(x 的值: %d\n,*p);// 通过指针访问 x 的值输出 10*p20;// 通过指针修改 x 的值printf(x 的新值: %d\n,x);// 输出 20十一、成员访问运算符用于访问结构体或联合体的成员。运算符含义示例说明.直接成员访问struct_var.member通过结构体变量访问成员-间接成员访问struct_ptr-member通过结构体指针访问成员等价于 (*ptr).memberstructPoint{intx,y;};structPointp{10,20};structPoint*ptrp;printf(%d\n,p.x);// 10printf(%d\n,ptr-y);// 20等价于 (*ptr).y十二、其他运算符运算符含义示例说明()函数调用func(a, b)调用函数[]下标访问arr[3]访问数组元素(type)强制类型转换(float)3将值转换为指定类型floatf(float)10/3;// 强制将 10 转为 float结果 3.333intarr[5]{1,2,3,4,5};intvalarr[2];// val 3十三、运算符优先级速查表从高到低优先级运算符结合性最高() [] - .从左到右↑! ~ – - * (type) sizeof从右到左单目↑* / %从左到右↑ -从左到右↑ 从左到右↑ 从左到右↑ !从左到右↑从左到右↑^从左到右↑|从左到右↑从左到右↑||从左到右↑?:从右到左三目↑ - * / % ^ | 从右到左最低,从左到右建议不必死记优先级表在复杂表达式中多用括号 () 来明确运算顺序既能提高可读性又能避免优先级错误。如果这篇文章对你有帮助欢迎点赞、收藏、关注主播是一个马上粉丝量超1个的嵌入式内容主播。谢谢