C 语言运算符的优先级和结合性

运算符的结合性和优先级

优先级运算符描述结合性
1()
[]
->
.
函数调用、数组下标、结构体 / 联合体成员通过指针访问、结构体 / 联合体成员访问从左到右
2!
~
++ (前缀)
-- (前缀)
+ (一元)
- (一元)
* (间接寻址)
& (取地址)
sizeof
(type)
逻辑非、按位取反、前缀自增、前缀自减、一元正号、一元负号、间接寻址、取地址、获取操作数的大小、类型转换从右到左
3*
/
%
乘法、除法、取模从左到右
4+
-
加法、减法从左到右
5<<
>>
左移、右移从左到右
6<
<=
>
>=
小于、小于等于、大于、大于等于从左到右
7==
!=
相等、不相等从左到右
8&按位与从左到右
9^按位异或从左到右
10<code>|</code>按位或从左到右
11&&逻辑与从左到右
12<code>||</code>逻辑或从左到右
13? :条件运算符(三元运算符)从右到左
14=
+=
-=
*=
/=
%=
<<=
>>=
&=
^=
<code>|=</code>
赋值、复合赋值运算符从右到左
15,逗号运算符从左到右

上手demo

#include <stdio.h>int main() {int a = 2, b = 3, c = 4;// 乘法优先级高于加法int result1 = a + b * c;  // 先计算 b * c,结果为 12,再加上 a,最终结果为 14printf("result1: %d\n", result1);  // 使用括号改变优先级int result2 = (a + b) * c;  // 先计算 a + b,结果为 5,再乘以 c,最终结果为 20printf("result2: %d\n", result2);  // 后缀自增和前缀自增int d = 5;int result3 = d++ + ++d;  // 先使用 d 的值 5 进行计算,然后 d 自增,再将自增后的 d(此时为 7)加 1,最终结果为 12printf("result3: %d\n", result3);  // 逻辑运算符int result4 = (a < b) && (b < c);  // 先计算 a < b 和 b < c,结果都为真,最终结果为 1printf("result4: %d\n", result4);  // 条件运算符int result5 = (a > b)? a : b;  // a 不大于 b,所以结果为 b 的值,即 3printf("result5: %d\n", result5);  // 复合赋值运算符a += b;  // 等价于 a = a + b,a 的结果为 5printf("a after +=: %d\n", a);  return 0;
}

括号运算符 ()

用于改变运算的优先级,也用于函数调用和类型转换,其在表达式中,括号内的运算总是优先进行。

#include <stdio.h>int main() {int a = 5, b = 3, c = 2;// 改变运算顺序int result1 = (a + b) * c;  // 先计算 a + b,结果为 8,再乘以 c,最终结果为 16printf("result1: %d\n", result1);  // 函数调用int sum(int x, int y) {return x + y;}int result2 = sum(a, b);  // 调用 sum 函数,将 a 和 b 的值传递给函数,结果为 8printf("result2: %d\n", result2);  // 类型转换float f = (float)a;  // 将整型 a 转换为浮点型,结果为 5.0printf("result3: %f\n", f);  return 0;
}

数组下标运算符 []

用于访问数组中的元,其下标必须是整数,可以是常量或变量。

*越界访问数组(使用超出数组长度的下标)会导致未定义行为!!!

#include <stdio.h>int main() {int arr[5] = {10, 20, 30, 40, 50};int index = 2;int element = arr[index];  // 访问数组 arr 中索引为 2 的元素,结果为 30printf("element: %d\n", element);  return 0;
}

结构体和联合体成员访问运算符 . 和 ->

  1. . 用于直接访问结构体或联合体的成员。
  2. -> 用于通过指针访问结构体或联合体的成员。
#include <stdio.h>
#include <stdlib.h>struct Point {int x;int y;
};int main() {struct Point p = {10, 20};// 直接访问成员int x = p.x;  // 访问结构体 p 的成员 x,结果为 10printf("x: %d\n", x);  struct Point *ptr = (struct Point *)malloc(sizeof(struct Point));ptr->x = 30;  // 通过指针访问成员 xptr->y = 40;  // 通过指针访问成员 yprintf("ptr->x: %d\n", ptr->x); printf("ptr->y: %d\n", ptr->y);  free(ptr);  return 0;
}

 一元运算符

逻辑非 !

对操作数取逻辑反,将非零值变为 0,当操作数 0 返回结果为 1。

#include <stdio.h>int main() {int a = 0;int result =!a;  // 结果为 1printf("result: %d\n", result);  return 0;
}

按位取反 ~

对操作数的二进制表示按位取反,也包括符号位(0为正,1为负)

#include <stdio.h>int main() {int a = 5;  // 二进制: 0101int result = ~a;  // 结果为 -6(二进制: 1010)printf("result: %d\n", result);  return 0;
}

前缀 / 后缀自增 ++ 和前缀 / 后缀自减 --

  1. 前缀:将操作数加 / 减 1,再使用结果。
  2. 后缀:先使用操作数的值,将操作数加 / 减 1。
#include <stdio.h>int main() {int a = 5;int b = ++a;  // 前缀自增,a 先加 1 变为 6,b 为 6int c = a++;  // 后缀自增,使用 a 的值 6,然后 a 加 1 变为 7printf("b: %d, c: %d, a: %d\n", b, c, a);  return 0;
}

一元正号 + 和一元负号 -

  1. +:不改变操作数的值,主要用于明确表示正数
  2. -:对操作数取负
#include <stdio.h>int main() {int a = 5;int b = -a;  // 结果为 -5int c = +a;  // 结果为 5printf("b: %d, c: %d\n", b, c);  return 0;
}

间接寻址 * 和取地址 &

  1. *:解引用指针,获取指针访问所指向的
  2. &:获取变量的地址
#include <stdio.h>int main() {int a = 10;int *ptr = &a;  // 获取 a 的地址存储在 ptr 中int value = *ptr;  // 通过 ptr 访问 a 的值,结果为 10printf("value: %d\n", value);  return 0;
}

sizeof 运算符

获取操作数的大小(以字节为单位)。

#include <stdio.h>int main() {int a;size_t size = sizeof(a);  // 获取 int 类型的大小,通常为 4printf("size: %zu\n", size);  return 0;
}

类型转换 (type)

将操作数转换为指定的数据类型。当是多精度转单精度类型时,可能导致数据丢失(如浮点数转整数)或截断。

#include <stdio.h>int main() {double d = 3.14;int i = (int)d;  // 将双精度浮点数转换为整数,结果为 3printf("i: %d\n", i);  return 0;
}

算术运算符

乘法 * 和除法 /

  1. *:两个操作数相乘。
  2. /:两个操作数相除,对于整数除法,结果会舍去小数部分;对于浮点数除法,使用 float 或 double 类型。
#include <stdio.h>int main() {int a = 10, b = 3;int product = a * b;  // 结果为 30int quotient = a / b;  // 结果为 3(整数除法)printf("product: %d, quotient: %d\n", product, quotient);  return 0;
}

取模 %

计算两个整数相除的余数。操作数必须是整数,否则会导致编译错误!!!

#include <stdio.h>int main() {int a = 10, b = 3;int remainder = a % b;  // 结果为 1printf("remainder: %d\n", remainder);  return 0;
}

加法 + 和减法 -

  1. +:两个操作数相加。
  2. -:两个操作数相减。
#include <stdio.h>int main() {int a = 5, b = 3;int sum = a + b;  // 结果为 8int difference = a - b;  // 结果为 2printf("sum: %d, difference: %d\n", sum, difference);  return 0;
}

移位运算符

左移 <<

将操作数的二进制表示向左移动指定的位数,右边补 0。

#include <stdio.h>int main() {int a = 5;  // 二进制: 0101int result = a << 2;  // 左移 2 位,结果为 20(二进制: 10100)printf("result: %d\n", result);  return 0;
}

右移 >>

将操作数的二进制表示向右移动指定的位数,对于无符号数左边补 0,对于有符号数根据编译器和系统可能补 0 或符号位。

#include <stdio.h>int main() {int a = 10;  // 二进制: 1010int result = a >> 1;  // 右移 1 位,结果为 5(二进制: 0101)printf("result: %d\n", result);  return 0;
}

 关系运算符:<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、==(相等)、!=(不相等)

用于比较两个操作数的大小或相等性,结果为 1(真)或 0(假)。

#include <stdio.h>int main() {int a = 5, b = 3;int less_than = a < b;  // 结果为 0(假)int less_than_or_equal = a <= b;  // 结果为 0(假)int greater_than = a > b;  // 结果为 1(真)int greater_than_or_equal = a >= b;  // 结果为 1(真)int equal = a == b;  // 结果为 0(假)int not_equal = a!= b;  // 结果为 1(真)printf("less_than: %d, less_than_or_equal: %d, greater_than: %d, greater_than_or_equal: %d, equal: %d, not_equal: %d\n", less_than, less_than_or_equal, greater_than, greater_than_or_equal, equal, not_equal);  return 0;
}

位运算符

  1. 位运算符用于对二进制位进行操作,常用于底层编程、硬件控制和性能优化。
  2. 按位与 & 常用于清除某些位或检查特定位是否置位。
  3. 按位或 | 常用于设置某些位。
  4. 按位异或 ^ 常用于反转某些位或交换两个数的值(不使用临时变量)。

按位与 &

对操作数的每一位进行逻辑与操作,都为 1 时结果为 1,否则为 0。

#include <stdio.h>int main() {int a = 5;  // 二进制: 0101int b = 3;  // 二进制: 0011int result = a & b;  // 结果为 1(二进制: 0001)printf("result: %d\n", result);  return 0;
}

按位异或 ^

对操作数的每一位进行逻辑异或操作,不同为 1,相同为 0。

#include <stdio.h>int main() {int a = 5;  // 二进制: 0101int b = 3;  // 二进制: 0011int result = a ^ b;  // 结果为 6(二进制: 0110)printf("result: %d\n", result);  return 0;
}

按位或 |

对操作数的每一位进行逻辑或操作,有一个为 1 时结果为 1,否则为 0。

#include <stdio.h>int a = 5;  // 二进制: 0101int b = 3;  // 二进制: 0011int result = a | b;  // 结果为 7(二进制: 0111)printf("result: %d\n", result);  return 0;
}

逻辑运算符

逻辑与 && 和逻辑或 || 具有短路特性,即对于 &&,如果第一个操作数为假,则不计算第二个操作数;对于 ||,如果第一个操作数为真,则不计算第二个操作数。

逻辑与 &&

当且仅当两个操作数都为真(非零)时,结果为真。

#include <stdio.h>int main() {int a = 5, b = 0;int result = (a > 0) && (b > 0);  // 结果为 0(假)printf("result: %d\n", result);  return 0;
}

逻辑或 ||

当两个操作数中至少有一个为真时,结果为真。

#include <stdio.h>int main() {int a = 5, b = 0;int result = (a > 0) || (b > 0);  // 结果为 1(真)printf("result: %d\n", result);  return 0;
}

条件运算符(三元运算符)

根据条件表达式的结果选择两个表达式中的一个,condition? expression1 : expression2,如果 condition 为真,结果为 expression1,否则为 expression2

#include <stdio.h>int main() {int a = 5, b = 3;int max = (a > b)? a : b;  // 结果为 5printf("max: %d\n", max);  return 0;
}

赋值运算符:=+=-=*=/=%=<<=>>=&=^=|=

将右侧表达式的值赋给左侧的变量。赋值表达式的值就是被赋的值。例如,int b = (a = 5); 中,先将 5 赋给 a,然后将 a 的值赋给 b

#include <stdio.h>int main() {int a;a = 10;  // 将 10 赋值给 aprintf("a: %d\n", a);  return 0;
}

复合赋值运算符

结合了算术、移位或位运算与赋值操作,提高代码的简洁性,先进行算术、移位或位运算,然后将结果赋给左侧变量。

#include <stdio.h>int main() {int a = 5;a += 3;  // 等价于 a = a + 3,结果为 8a -= 2;  // 等价于 a = a - 2,结果为 6a *= 4;  // 等价于 a = a * 4,结果为 24a /= 3;  // 等价于 a = a / 3,结果为 8a %= 5;  // 等价于 a = a % 5,结果为 3a <<= 1;  // 等价于 a = a << 1,结果为 6(二进制:110)a >>= 1;  // 等价于 a = a >> 1,结果为 3(二进制:011)a &= 2;  // 等价于 a = a & 2,结果为 2(二进制:010)a ^= 1;  // 等价于 a = a ^ 1,结果为 3(二进制:011)a |= 4;  // 等价于 a = a | 4,结果为 7(二进制:111)printf("a: %d\n", a);  return 0;
}

逗号运算符 ,

从左到右依次计算操作数,并返回最后一个操作数的值。

#include <stdio.h>int main() {int a = (1, 2, 3);  // 结果为 3int b = 5, c = 10;int d = (b++, c++, b + c);  // 先执行 b++ 和 c++,然后计算 b + c,结果为 17printf("a: %d, d: %d\n", a, d);  return 0;
}

常用于在 for 循环的初始化或更新部分中执行多个操作

#include <stdio.h>int main() {for (int i = 0, j = 10; i < 5; i++, j--) {printf("i: %d, j: %d\n", i, j);}return 0;
}
运算符优先级和结合性
  1. 优先级
    1. 运算符的优先级决定了表达式中运算的顺序,在复杂表达式中可能导致混淆。例如,在 a + b * c 中,先计算乘法 b * c,再计算加法。为避免混淆,可使用括号明确运算顺序,如 (a + b) * c
  2. 结合性
    1. 从左到右结合性:大多数二元运算符是从左到右结合的,如 a + b + c 先计算 a + b,再加上 c
    2. 从右到左结合性:一元运算符和赋值运算符通常是从右到左结合的,如 a = b = c 先将 c 赋给 b,再将 b 的值赋给 a

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3131.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

B站评论系统的多级存储架构

1. 背景 评论是 B站生态的重要组成部分&#xff0c;涵盖了 UP 主与用户的互动、平台内容的推荐与优化、社区文化建设以及用户情感满足。B站的评论区不仅是用户互动的核心场所&#xff0c;也是平台运营和用户粘性的关键因素之一&#xff0c;尤其是在与弹幕结合的情况下&#xf…

若依分页插件失效问题

若依对数据二次处理导致查询total只有十条的问题处理办法_若依分页查询total-CSDN博客

css盒子水平垂直居中

目录 1采用flex弹性布局&#xff1a; 2子绝父相margin&#xff1a;负值&#xff1a; 3.子绝父相margin:auto&#xff1a; 4子绝父相transform&#xff1a; 5通过伪元素 6table布局 7grid弹性布局 文字 水平垂直居中链接&#xff1a;文字水平垂直居中-CSDN博客 以下为盒子…

Golang Gin系列-3:Gin Framework的项目结构

在Gin教程的第3篇&#xff0c;我们将讨论如何设置你的项目。这不仅仅是把文件扔得到处都是&#xff0c;而是要对所有东西的位置做出明智的选择。相信我&#xff0c;这些东西很重要。如果你做得对&#xff0c;你的项目会更容易处理。当你以后不再为了找东西或添加新功能而绞尽脑…

03JavaWeb——Ajax-Vue-Element(项目实战)

1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据&#xff0c;如下图所示的表格中的学生信息&#xff0c;应该来自于后台&#xff0c;那么我们的后台和前端是互不影响的2个程序&#xff0c;那么我们前端应该如何从后台获取数据呢&#xff1f;因为是2个程序&#xf…

【无法下载github文件】虚拟机下ubuntu无法拉取github文件

修改hosts来进行解决。 步骤一&#xff1a;打开hosts文件 sudo vim /etc/hosts步骤二&#xff1a;查询 github.com的ip地址 https://sites.ipaddress.com/github.com/#ipinfo将github.com的ip地址添加到hosts文件末尾&#xff0c;如下所示。 140.82.114.3 github.com步骤三…

【Idea启动项目报错NegativeArraySizeException】

项目场景&#xff1a; Idea启动项目报错&#xff08;打包不报错&#xff09;&#xff0c;项目在服务器部署运行没有问题&#xff0c;尝试了重启idea、重启电脑、maven clean/install 都不行 maven-resources-production:sample: java.lang.NegativeArraySizeException: -5833…

【 MySQL 学习2】常用命令

文章目录 一、基础命令1.1、登录1.2 、退出1.3、查看数据库中有哪些数据库1.4 、选择使用的数据库1.5、创建数据库1.6 查看哪个数据库下有哪些表 二、SQL语句的分类2.1 DQL 数据查询语言2.2 DML 数据操作语言2.3 DDL 数据定义语言2.4 TCL 事物控制语言2.5 DCL 数据控制语言 三、…

JVM直击重点

JVM直击重点 JVM内存模型 JVM中类加载器分类与核心功能 Java里有如下几种类加载器 引导类加载器&#xff1a;负责加载支撑JVM运行的位于JRE的lib目录下的核心类库&#xff0c;比如rt.jar、charsets.jar等 扩展类加载器&#xff1a;负责加载支撑JVM运行的位于JRE的lib目录下的e…

图数据库 | 18、高可用分布式设计(中)

上文我们聊了在设计高性能、高可用图数据库的时候&#xff0c;从单实例、单节点出发&#xff0c;一般有3种架构演进选项&#xff1a;主备高可用&#xff0c;今天我们具体讲讲分布式共识&#xff0c;以及大规模水平分布式。 主备高可用、分布式共识、大规模水平分布式&#xff…

【常见BUG】Spring Boot 和 Springfox(Swagger)版本兼容问题

???欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老…

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示&#xff0c;特别是在使用一些特定于 Vite 的功能时&#xff08;如 import.meta.env&#xff09;。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…

数字化时代,传统代理模式的变革之路

在数字化飞速发展的今天&#xff0c;线上线下融合&#xff08;O2O&#xff09;成了商业领域的大趋势。这股潮流&#xff0c;正猛烈冲击着传统代理模式&#xff0c;给它带来了新的改变。 咱们先看看线上线下融合现在啥情况。线上渠道那是越来越多&#xff0c;企业纷纷在电商平台…

接口测试自动化实战(超详细的)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前言 自从看到阿里云性能测试 PTS 接口测试开启免费公测&#xff0c;就想着跟大家分享交流一下如何实现高效的接口测试为出发点&#xff0c;本文包含了我在接口测…

意图颠覆电影行业的视频生成模型:Runway的Gen系列

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Runway开发的视频生成模型Gen系列&#xff0c;包括Gen-1、Gen-2和Gen3 Alpha等&#xff0c;这些模型每次发布都震惊AI圈&#xff0c;荣获多个视频生成的…

ant design vue的级联选择器cascader的悬浮层样式怎么修改

平时想要修改组件内定样式会使用穿透deep和&#xff01;important调优先级&#xff0c;但是在这里都不行&#xff0c;样式都不能改变 后来尝试出来是因为加了scoped&#xff0c;样式不起作用&#xff0c;但是不能直接去掉scoped&#xff0c;别的样式会受到影响&#xff0c;单独…

linux手动安装mysql5.7

一、下载mysql5.7 1、可以去官方网站下载mysql-5.7.24-linux-glibc2.12-x86_64.tar压缩包&#xff1a; https://downloads.mysql.com/archives/community/ 2、在线下载&#xff0c;使用wget命令&#xff0c;直接从官网下载到linux服务器上 wget https://downloads.mysql.co…

使用 ChatGPT 生成和改进你的论文

文章目录 零、前言一、操作引导二、 生成段落或文章片段三、重写段落四、扩展内容五、生成大纲内容六、提高清晰度和精准度七、解决特定的写作挑战八、感受 零、前言 我是虚竹哥&#xff0c;目标是带十万人玩转ChatGPT。 ChatGPT 是一个非常有用的工具&#xff0c;可以帮助你…

TinyEngine v2.1版本发布:全新的区块方案和画布通信方案,打造更强力的可拓展低代码引擎

前言 2025年蛇年已经到来&#xff0c;TinyEngine v2.1.0 版本也已经蛇气腾腾的发布了出来&#xff0c;新年新气象&#xff0c;为了让大家更详细了解到 v2.1.0 的内容更新&#xff0c;我们特此列举了该版本中的一些重要特性更新。 v2.1.0变更特性概览 1、使用了新的纯前端区块…

【机器学习实战入门】使用OpenCV和Keras的驾驶员疲劳检测系统

嗜睡驾驶者警报系统 防止司机疲劳驾驶警报系统 中级 Python 项目 - 司机疲劳检测系统 疲劳检测是一种安全技术&#xff0c;能够预防因司机在驾驶过程中入睡而造成的事故。 本中级 Python 项目的目标是建立一个疲劳检测系统&#xff0c;该系统将检测到一个人的眼睛闭合了一段时…