首页 > 其他分享 >C语言运算符深度解析--超详细

C语言运算符深度解析--超详细

时间:2024-08-01 22:17:52浏览次数:14  
标签:变量 -- C语言 运算符 二进制 int 表达式 赋值

引言

在C语言的浩瀚宇宙中,运算符如同点亮星辰的魔法棒,它们不仅连接着数据的海洋,更驱动着程序的逻辑流转。从基础的算术运算到复杂的位操作,每一个运算符都承载着特定的功能,是构建程序逻辑的基石。掌握C语言的运算符,就如同手握开启编程世界大门的钥匙,让你能够自如地编写出高效、精准的代码。本文将带你深入探索C语言的运算符世界一一解析它们的奥秘,助你在编程之路上越走越远。


算术运算符

运算符 描述 示例
+ 加法运算符,用于将两个数相加 int result = 5 + 3; // 结果为 8
- 减法运算符,用于从一个数中减去另一个数 int result = 10 - 4; // 结果为 6
* 乘法运算符,用于将两个数相乘 int result = 3 * 4; // 结果为 12
/ 除法运算符,用于将第一个数除以第二个数 int quotient = 10 / 2; // 结果为 5
float division = 10.0 / 3.0; // 结果为 3.333...
% 取模运算符(求余),返回两数相除的余数 int remainder = 10 % 3; // 结果为 1
++ 自增运算符,将变量的值增加1 int a = 5; a++; // a 的值变为 6
int b = 5; ++b; // b 的值同样变为 6
-- 自减运算符,将变量的值减少1 int c = 5; c--; // c 的值变为 4
int d = 5; --d; // d 的值同样变为 4

注意:

  • 当使用/运算符进行整数除法时,结果会向下取整,即舍弃小数部分。
  • %运算符的操作数必须是整数。
  • 自增(++)和自减(--)运算符可以放在变量之前(前缀形式)或之后(后缀形式),但在表达式中的行为可能有所不同。前缀形式会先增加(或减少)变量的值,然后再进行其他操作;后缀形式则会先进行其他操作,然后再增加(或减少)变量的值。但在这个表格的示例中,我们主要关注它们的基本用法。


关系运算符

运算符 描述 示例
== 等于,比较两个值是否相等 if (5 == 3) { /* 这部分代码不会执行 */ }
if (5 == 5) { /* 这部分代码会执行 */ }
!= 不等于,比较两个值是否不相等 if (5 != 3) { /* 这部分代码会执行 */ }
if (5 != 5) { /* 这部分代码不会执行 */ }
> 大于,比较第一个值是否大于第二个值 if (5 > 3) { /* 这部分代码会执行 */ }
if (5 > 5) { /* 这部分代码不会执行 */ }
< 小于,比较第一个值是否小于第二个值 if (3 < 5) { /* 这部分代码会执行 */ }
if (5 < 3) { /* 这部分代码不会执行 */ }
>= 大于等于,比较第一个值是否大于或等于第二个值 if (5 >= 5) { /* 这部分代码会执行 */ }
if (3 >= 5) { /* 这部分代码不会执行 */ }
<= 小于等于,比较第一个值是否小于或等于第二个值 if (3 <= 5) { /* 这部分代码会执行 */ }
if (5 <= 3) { /* 这部分代码不会执行 */ }

注意:

  • 关系运算符用于比较两个值,并返回一个布尔结果(在C语言中,实际上是以整数形式返回,其中0表示false,非0值表示true)。
  • 这些运算符经常与ifwhilefor等控制流语句一起使用,以根据条件执行不同的代码块。
  • 在进行比较时,确保比较的数据类型兼容,否则可能会引发编译错误或意外的行为。例如,将整数与浮点数直接进行比较通常不是一个好主意,除非你有意为之并了解可能的结果。


逻辑运算符

运算符 描述 示例
&& 逻辑与(AND),仅当两个操作数都为真时,结果才为真 if (a > 0 && b > 0) { /* 当a和b都大于0时执行 */ }
|| 逻辑或(OR),当两个操作数中至少有一个为真时,结果就为真 if (a > 0 || b > 0) { /* 当a或b中至少有一个大于0时执行 */ }
! 逻辑非(NOT),用于反转操作数的真假值 if (!a) { /* 当a为假时执行 */ }if (!(a > 0)) { /* 当a不大于0时执行 */ }

注意:

  • 逻辑运算符通常用于控制流语句(如ifwhilefor)中,以根据多个条件的组合来决定是否执行某个代码块。
  • 在C语言中,真值通常表示为非零值,而假值则表示为0。因此,逻辑运算符的操作数可以是任何整数表达式,其真假值取决于表达式的计算结果。
  • 使用逻辑运算符时,应注意运算符的优先级和结合性。通常,!运算符的优先级最高,&&||运算符的优先级低于关系运算符和算术运算符,但高于赋值运算符。此外,&&||运算符是左结合的,即它们从左到右评估操作数。
  • 逻辑与(&&)运算符具有短路行为,即如果第一个操作数为假(即0),则不会评估第二个操作数,因为整个表达式的结果已经确定为假。同样,逻辑或(||)运算符也具有短路行为,即如果第一个操作数为真(即非0),则不会评估第二个操作数,因为整个表达式的结果已经确定为真。这种短路行为有时可以用于避免不必要的计算或潜在的副作用。


位运算符

运算符 描述 示例
& 按位与(AND),对两个数的二进制表示进行逐位与操作,只有对应的两个二进位均为1时,结果位才为1 int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a & b; // 结果: 1, 二进制: 0001
| 按位或(OR),对两个数的二进制表示进行逐位或操作,只要对应的两个二进位中有一个为1时,结果位就为1 int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a | b; // 结果: 7, 二进制: 0111
^ 按位异或(XOR),对两个数的二进制表示进行逐位异或操作,当对应的两个二进位相异时,结果位为1 int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a ^ b; // 结果: 6, 二进制: 0110
~ 按位取反(NOT),对数的二进制表示进行逐位取反操作,即0变1,1变0 int a = 5; // 二进制: 0101
int b = ~a; // 结果: -6, 二进制(补码): 11111010(注意:结果以补码形式存储,实际值需考虑数据类型和符号位)
<< 左移(Left Shift),将数的二进制表示向左移动指定的位数,左侧超出的位将被丢弃,右侧新增的位将用0填充 int a = 5; // 二进制: 0101
int b = a << 2; // 结果: 20, 二进制: 10100
>> 右移(Right Shift),将数的二进制表示向右移动指定的位数,对于有符号数,左侧新增的位将用符号位填充(即正数用0填充,负数用1填充),右侧超出的位将被丢弃 int a = 5; // 二进制: 0101
int b = a >> 2; // 结果: 1, 二进制: 0001
int c = -5; // 假设为32位整数,二进制(补码): 11111111 11111111 11111111 11111011
int d = c >> 2; // 结果: -2, 二进制(补码): 11111111 11111111 11111111 11111110

注意

  1. 位运算符的操作数通常是整数类型(如intchar等),不能是浮点类型(如floatdouble)。
  2. 在进行位移操作时,特别是右移操作,对于有符号数,不同编译器或平台可能有不同的行为(即算术右移或逻辑右移),因此在跨平台编程时需要特别注意。
  3. 位运算符常用于底层编程、硬件编程、性能优化等场景,它们允许程序员直接对数据的二进制表示进行操作,从而实现高效的数据处理和算法实现。
  4. 示例中的结果以十进制形式给出,但为了说明位运算的过程,同时也给出了二进制形式的说明(对于取反操作,由于结果以补码形式存储,因此直接给出了补码形式的二进制表示和对应的十进制值)。在实际编程中,需要注意数据类型和符号位对结果的影响。


赋值运算符

运算符 描述 示例
= 简单的赋值运算符,用于将右侧表达式的值赋给左侧的变量 int a = 5; // 将5赋值给变量a
+= 加法赋值运算符,将右侧表达式的值与左侧变量的值相加,然后将结果赋值给左侧变量 a += 3; // 相当于 a = a + 3; 假设a之前的值为5,则执行后a的值为8
-= 减法赋值运算符,将左侧变量的值减去右侧表达式的值,然后将结果赋值给左侧变量 a -= 2; // 相当于 a = a - 2; 假设a之前的值为8,则执行后a的值为6
*= 乘法赋值运算符,将左侧变量的值与右侧表达式的值相乘,然后将结果赋值给左侧变量 a *= 2; // 相当于 a = a * 2; 假设a之前的值为6,则执行后a的值为12
/= 除法赋值运算符,将左侧变量的值除以右侧表达式的值,然后将结果赋值给左侧变量 a /= 2; // 相当于 a = a / 2; 假设a之前的值为12,则执行后a的值为6
%= 取模赋值运算符,将左侧变量的值对右侧表达式的值取模,然后将结果赋值给左侧变量 a %= 3; // 相当于 a = a % 3; 假设a之前的值为6,则执行后a的值为0
<<= 左移赋值运算符,将左侧变量的二进制表示向左移动指定的位数(由右侧表达式给出),然后将结果赋值给左侧变量 a <<= 1; // 相当于 a = a << 1; 假设a之前的值为6(二进制: 0110),则执行后a的值为12(二进制: 1100)
>>= 右移赋值运算符,将左侧变量的二进制表示向右移动指定的位数(由右侧表达式给出),然后将结果赋值给左侧变量 a >>= 1; // 相当于 a = a >> 1; 假设a之前的值为12(二进制: 1100),则执行后a的值为6(二进制: 0110),对于有符号数,注意符号位的扩展
&= 按位与赋值运算符,对左侧变量的值和右侧表达式的值进行按位与操作,然后将结果赋值给左侧变量 a &= 3; // 相当于 a = a & 3; 假设a之前的值为12(二进制: 1100),则执行后a的值为0(二进制: 0000),因为1100 & 0011 = 0000
|= 按位或赋值运算符,对左侧变量的值和右侧表达式的值进行按位或操作,然后将结果赋值给左侧变量 a |= 3; // 相当于 a = a | 3; 假设a之前的值为4(二进制: 0100),则执行后a的值为7(二进制: 0111),因为0100 | 0011 = 0111
^= 按位异或赋值运算符,对左侧变量的值和右侧表达式的值进行按位异或操作,然后将结果赋值给左侧变量 a ^= 3; // 相当于 a = a ^ 3; 假设a之前的值为4(二进制: 0100),则执行后a的值为7(二进制: 0111),因为0100 ^ 0011 = 0111

注意

  • 赋值运算符用于将表达式的值存储到变量中。
  • 复合赋值运算符(如+=-=等)是先进行指定的算术或位运算,然后将结果赋值给左侧的变量,这种方式可以使代码更简洁。
  • 在使用位运算符(如<<=>>=&=\|=^=)时,需要注意操作数的数据类型和符号位的影响,特别是在进行右移操作时。
  • 赋值运算的结果通常是赋值给左侧的变量,但某些情况下(如在表达式中使用赋值运算符),其结果也可以被用于其他目的。然而,为了代码的可读性和可维护性,建议避免在需要计算结果的表达式中使用赋值运算符。


杂项运算符

运算符 描述 示例
sizeof 用于获取变量或数据类型所占内存的大小(以字节为单位) size_t size = sizeof(int); // 获取int类型所占的字节数,结果通常为4(取决于编译器和平台)
&(地址运算符) 获取变量的内存地址 int a = 5; int* ptr = &a; // ptr存储了变量a的内存地址
*(解引用/间接访问运算符) 通过指针访问其所指向的内存地址中的值 int* ptr = &a; int value = *ptr; // value的值为5,即a的值
?:(条件运算符/三元运算符) 根据条件表达式的真假来选择两个值中的一个 int a = 10, b; b = (a > 5) ? 20 : 30; // b的值为20,因为a大于5

注意

  1. sizeof运算符的返回值类型为size_t,这是一个无符号整数类型,用于表示对象的大小。

  2. 地址运算符&用于获取变量的内存地址,其结果是一个指向该变量类型的指针。

  3. 解引用/间接访问运算符*用于通过指针访问其所指向的内存地址中的值。如果指针未初始化或指向无效的内存地址,则解引用该指针可能导致未定义行为。

  4. 条件运算符?:是一个三元运算符,它接受三个操作数:条件表达式、当条件为真时返回的值、以及当条件为假时返回的值。其优先级低于关系运算符和算术运算符,但高于赋值运算符。

  5. 杂项运算符在C语言中扮演着重要的角色,它们提供了对内存地址的直接操作、条件选择等功能,是编写高效、灵活C语言程序的关键。然而,由于它们直接操作内存地址或进行条件选择,因此在使用时需要格外小心,以避免引入错误或安全问题。


运算符优先级

优先级 运算符 描述 用法示例
1 括号 () 用于改变运算的优先级 (a + b) * c
2 自增 ++、自减 --、正负号 +-、逻辑非 !、按位取反 ~ 单目运算符,作用于单个操作数 ++a, --b, +5, -3, !flag, ~x
3 乘法 *、除法 /、取模 % 双目运算符,用于算术运算 a * b, c / d, e % f
4 加法 +、减法 - 双目运算符,用于算术运算 g + h, i - j
5 左移 <<、右移 >> 双目运算符,用于位运算 k << 2, l >> 1
6 关系运算符(大于 >, 大于等于 >=, 小于 <, 小于等于 <= 双目运算符,用于比较操作数 m > n, o >= p, q < r, s <= t
7 等于 ==、不等于 != 双目运算符,用于比较操作数是否相等 u == v, w != x
8 按位与 & 双目运算符,用于位运算 y & z
9 按位异或 ^ 双目运算符,用于位运算 a ^ b
10 按位或 | 双目运算符,用于位运算 c | d
11 逻辑与 && 双目运算符,用于逻辑运算 e && f
12 逻辑或 || 双目运算符,用于逻辑运算 g || h
13 条件运算符 ?: 三目运算符,根据条件选择两个值中的一个 i > 0 ? i : -i
14 赋值运算符 =+=-=*=/=%=&=^=|=<<=>>= 用于将值赋给变量或进行复合赋值 j = 5, k += 3
15 逗号运算符 , 用于分隔表达式,并返回最后一个表达式的值 m = 1, n = 2, m + n(结果为3,但m和n也被赋值)
注意
  1. 运算符优先级决定了在一个表达式中各个运算符的执行顺序。当表达式中存在多个运算符时,优先级高的运算符会先进行计算。

  2. 可以通过使用括号()来改变运算符的优先级,使得括号内的表达式先被计算。

  3. 赋值运算符的优先级相对较低,这意味着在复杂的表达式中,赋值操作通常会在其他算术、逻辑或位运算之后进行。

  4. 逗号运算符,用于分隔多个表达式,并返回最后一个表达式的值。它在所有运算符中具有最低的优先级,因此逗号两边的表达式会按照从左到右的顺序依次计算。

请注意,虽然这个表格提供了C语言运算符优先级的基本概述,但在实际编程中,为了代码的可读性和易于理解,建议尽量使用括号来明确表达式的计算顺序。

标签:变量,--,C语言,运算符,二进制,int,表达式,赋值
From: https://www.cnblogs.com/kdgoat/p/18337695

相关文章

  • 如何使用图片的exif信息计算相机焦距
    在做三维重建和视觉测量的应用中,如果不想做复杂的相机标定,那么可以从图像的exif信息中获取相机的焦距信息。这里提供两种方法:1.通过35mm等效焦距来计算:图像的exif信息可以从图像的属性中获取,例如下图中,可以看出35mm等效焦距为35mm,根据35mm胶片的尺寸为36mmx24mm,那么相机的焦......
  • 8.1 星露谷真好玩
    在体验星露谷物语的过程中,我体会到规划对于农场发展的重要性。刚开始时,由于缺乏经验,农场布局常常不尽如人意,不仅浪费空间还影响效率。然而,随着对游戏的摸索和熟悉,我可以更合理的安排作物种植区域、动物棚舍以及设施的位置,使农场运作更加高效有序。这一过程让我联想到项目管理和......
  • Openfiles /?     允许管理员列出系统上已打开的文件和文件夹或与其断开连接。
     openfiles|MicrosoftLearn 信息:需要启动系统全局标志“维护对象列表”才能查看   本地打开的文件。   请参阅Openfiles/?以获得详细信息。通过本地共享点远程打开的文件:---------------------------------------------信息:没有找到打开的共享文件......
  • OracleLinux9安装GlusterFS nfs-Ganesha
    安装环境系统信息NAME="OracleLinuxServer"VERSION="9.4"ID="ol"ID_LIKE="fedora"VARIANT="Server"VARIANT_ID="server"VERSION_ID="9.4"PLATFORM_ID="platform:el9"PRETTY_NAME="......
  • JWT
    我喜欢你,是那种一想到你的名字,心里动辄海啸山鸣的喜欢。--zhuSession缺点1、对于分布式集群环境,Session数据保存在服务器内存中就不合适了,应该放到一个中心状态服务器上。ASP.NETCore支持Session采用Redis、Memcached。2、中心状态服务器有性能问题。JWTJWT(JSONWebToken)......
  • 2024牛客暑期多校训练营6
    Abstract好难qwqA-CakeIdea全是博弈!首先来解释题目意思。phase1:给出一颗树,根节点为1,树上每一条边的权值为0或者1。初始时刻,根节点处有一只小马,小G和小O依次控制小马移动,每次只能向子节点移动,若当前节点是叶节点,phase1结束。在移动的过程中,需要记录经过的边的......
  • 数论
    一。数论基础1)数论函数数论函数指定义域为正整数的函数。数论函数也可以视作一个数列。2)积性函数如果对于f(n),f(1)=1,若(x,y)=1则f(xy)=f(x)f(y),称其为积性函数。如果对于f(n),f(1)=1,有f(xy)=f(x)f(y),称其为完全积性函数。二。约数最大公约数求最大公约数:欧几里得算法gcd......
  • 2024牛客暑期多校训练营6 A Cake
    题目大意详细题目传送门\(A\)和\(B\)要从轮流走,从根到一个叶子节点位置,\(A\)先。树有边权\(0,1\),按照顺序经过的边权按字符串拼接得到一个串\(S\)。现在\(B\)可以把\(1\)拆分成任意个分数(但不能超过\(S\)的长度,且分数可以为空,)两人按照\(S\)串的顺序选取,如果\(S_......
  • ObjectARX 判断实体是否是在位编辑块对象简单例子
    判断使用acdbIsInLongTransaction应该就可以。ads_nameent;ads_pointpt;if(RTNORM!=acedEntSel(_T("\n选择对象:"),ent,pt)){return;}AcDbObjectIdobjId;acdbGetObjectId(objId,ent);//直接判断//if(acdbIsInLongTransaction......
  • 喜报 | 极限科技入选北京市 2024 年第一批科技中小企业名单
    2024年7月24日,北京市科学技术委员会、中关村科技园区管理委员会发布《关于北京市2024年第一批拟入库科技型中小企业名单的公示》。根据《科技型中小企业评价办法》(国科发政〔2017〕115号)和《科技型中小企业评价服务工作指引》(国科火字〔2022〕67号)有关规定,极限数据(北......