【C语言】操作符 精准讲解(上)

简介: 【C语言】操作符 精准讲解(上)

本章介绍:

  1. 各种操作符的全方位讲解。
  2. 表达式求值


操作符分类:



1 算术操作符


+            /    %


  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。


  • 除法 / 得到的是商
  • 除法操作符的两个操作数都是整数的话,执行的是整数除法 。 用(%d打印)
  • 除法操作符的两个操作数只要有一个浮点数,执行的是小数除法。用(%lf打印)
  • $取模 % (取余)得到的是余数
  • 取模操作符的操作数必须是整数


2 移位操作符


<<左移操作符

> > 左移操作符

注:移位操作符的操作数只能是整数。


  • <<左移操作符

1: 左移动操作符:左边丢弃,右边补0,(符号位也跟着丢)

2: 每左移一位是乘2的效果


被左移时候的值是不变的,更动的赋值那个数

相当于 int a = -3; int b = a - 1;a的值是不跟着变化的


4fe604c7b44b4adfa024710d3564e9e8.png


  • >>左移操作符

移位规则:

每右移一位是除2的效果

首先右移运算分两种:


  • 1.逻辑移位

左边用0填充,右边丢弃

1. 算书移位

左边用原该值的符号位填充,右边丢弃


移位图解:


de98ddaed87c4b0ba2617763972d3af2.png


  • 右移的时候,到底采用的是算术右移?还是逻辑右移,是取决于编译器的!

在 V S 编译器里采用的是算术右移


(要用负数去测试)

如果逻辑右移,移动一位时候符号位变成0,是正数

如果算术左移,移动一位时候符号位变成1,是负数



  • 9a9aa20276714dfc821d2bab6b5d076d.png


警告

对于移位运算符,不要移动负数位,这个是标准未定义的。

例如:


int num = 10;
num>>-1; //error


3 位操作符


(位操作都是二进制位进行计算 )


位操作符有:


&      按位与 ( 有0出0,全1出一)

∣       按位或 ( 全0出0, 有1出1 )

 ˆ      按位异或 ( 相异出1, 相同出0)

注:他们的操作数必须是整数。


为了更好让大家理解,我还是以举二个例子的方式进行讲解~


  • 编写代码实现:求一个整数存储在内存中的二进制中1的个数


方法一:按位与 &

按位循环1~32位,并分别与1按位与,因为&1时二进制只最低位是1,每次右移一次都会跟1比较( 有0出0,全1出一),当得到1的时候count++就可以得出二进制中有多少个1,代码如下:


整数在内存中存储的是: 补码(2进制)

15的二进制有4个10000000000000000000000001111


6f1e0b21f3f840dd927d1b62faea8ffc.png


方法二:a&(a-1);


a&(a-1),第一时间肯定有点懵吧?不知道什么意思,我们举一个例子方便理解

ccb68732de3a43739327d0e213e1d071.png


)

每次 a & ( a − 1 ) 后 c o u n t + +

每次 a & ( a − 1 ) 当 32 位都为 0 的时候,这个值就为 0 了,也就数完 a 中有几个 1 了


0505d0892250429da7d10c2e8ad7d9c2.png


  • 不能创建临时变量(第三个变量),实现两个数的交换。

在交换两个数的时,常常我们想到的方法是先创建一个临时变量,将一个变量放到临时变量里,然后把另一个变量放到第一个变量里,最后把第一个存起来的变量再放到另一个变量,但是这题限制了创造临时变量。

方法一:

这可能是大多数人想出来的办法,先把a,b两个值加起来,存到a里面,然后把a-b存到b里面,最后再把a的值解去b的值,得到两个数的交换


这个代码存在一定的问题

如果a和b比较大,a和b相加会溢出!(因为int形的取值范围是-32768~32767)


6143321c0f1849a38871cec55492a22f.png


方法二:

^ 按位异或


e2d8586bd6164a8e84cc2691721119d0.png

1670eb253079407685d1660d7dd917ff.png


这样完美的解决了不能创建临时变量交换两个数的问题

但是这样的代码可读性不好,可能想半天都不知道干什么

所以在实际写代码时,还是创造两个临时变量来交换两个数

这里让大家更好的了解 ^的知识


4 赋值操作符


赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。


int weight = 120;//体重
weight = 89;//不满意就赋值


赋值操作符可以连续使用,比如:


int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值
这样的代码感觉怎么样?
那同样的语义,你看看:
x = y+1;
a = x;
这样的写法是不是更加清晰爽朗而且易于调试。


  • 复合赋值符:


+=

− =

∗ =

/ =

> > =

< < =

& =

∣ =

% =


这些运算符都可以写成复合的效果。

比如:


int x = 10;
x = x+10;
x += 10;复合赋值
其他运算符一样的道理。这样写更加简洁。


5 单目操作符


单目操作符介绍


!                   逻辑反操作

−                  负值

+                  正值

&                  取地址

s i z e o f          操作数的类型长度(以字节为单位)

− −             前置、后置 − −

+ +             前置、后置 + +

∗                   间接访问操作符 ( 解引用操作符 )

( 类型 )          强制类型转换

~ 对一个数的二进制按位取反


  • ! 逻辑反操作


如果flag为真第一个if就进去判断条件

如果flag为假 !(逻辑反操作)让flag变成真 if进去判断条件

00bff0c6a1c244be80b388571b940d71.png


  • &地址
  • ∗ 间接访问操作符 ( 解引用操作符 )


这两个操作符跟指针又密切的关系,都是搭配使用的


f5ad2b1e4ab4493786caf921091bd87f.png


  • sizeof:操作数的类型长度(以字节为单位)


126d9fae5788484ab3bea5669e299992.png


  • ++前置、后置++
  • − − 前置、后置 − −


- -前置:(先–,后使用) + +前置:(先+ +,后使用)

后置- -:(先使用,后–) 后置+ +:(先使用,后++)


总归前置是先++或者- -再使用

后置先使用再加减


7f5a0bec3d184256ad0fb4b515bd6749.png


()强制类型转换

如果一个运算符两遍的运算数据类型不同,先要将其转换为相同的类型,强制类型转换可以消除程序中的警告,即确保写代码的程序员自己清楚类型转换,允许丢失一定精度,或做类型匹配


如果两个不同类型的数据进行一起运算,会报出程序警告


58da6b133d96436082509961f9980d1f.png


强制类型转换就可以消除程序中的警告


  • ~ 对一个数的二进制按位取反


把数据的每个二进制位取反,即把0变成1,把1变成0。


57ebcbbc3a9a4cd4838c6edfbbec45b7.png


6 关系操作符


>

> =

<

< =

! =    用于测试“不相等”

= =   用于测试“相等”


这些关系运算符比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。


警告:


在编程的过程中 = = 和 = 不小心写错,导致的错误。


7 逻辑操作符


&&  逻辑与(都要是真的才可以执行)(并且)

∣ ∣       逻辑或 (只要一个为真就执行)(或者)


  • 区分逻辑与和按位与
  • 区分逻辑或和按位或

(&&)(||):逻辑与和或 :只关注真假(非0就是真,0就是假)

(&)(|) 按位与和按位或:二进制位进行计算


举例:

1&2----->0

1&&2---->1

1|2----->3

1||2---->1


  • 为了更好理解逻辑与和逻辑或,习题方式进行讲解

以下代码输出的是什么


#include <stdio.h>
int main()
{
    int i = 0,a=0,b=2,c =3,d=4;
    i = a++ && ++b && d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}


解析:


答案是 a=1 b=2 c=3 d=4

&& 是控制求值顺序的,当运算 a++ 的时候,因为 a++ 是后置++(先使用后++),所以 a++ 这时还是 0,a为0,逻辑或有一个为假,表达式不成立,则后面的运算就不用再算了,相当于电路中的‘短路’.


593f5e0215dd4503aaa3125f9fc1e13d.png


如果把代码改成这样输出的又是什么


int main()
{
  int i = 0, a = 0, b = 2, c = 3, d = 4;
  i = a++||++b||d++;
  printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
  return 0;
}


解析:


a=1 b=3 c=3 d=4

||逻辑或(只要一个为真就执行)

||(逻辑或)它是只要遇到 (非0值)为真,表达式整体为真,后面表达式就不要再算了。当遇到 a++ 是后置++(先使用后++),所以 a++ 这时还是 0 ,到下一个 ++b 运算,b为2(非0为真)表达式整体为真 那就停下来了,所以 d++ 不运算,所以最后d的值是不变的。


0c5c8ce1fa1b4b00ab64b0a6f8982795.png



目录
相关文章
|
3月前
|
存储 C语言 索引
【C语言篇】操作符详解(下篇)
如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。
72 0
|
3月前
|
程序员 编译器 C语言
【C语言篇】操作符详解(上篇)
这是合法表达式,不会报错,但是通常达不到想要的结果, 即不是保证变量 j 的值在 i 和 k 之间。因为关系运算符是从左到右计算,所以实际执⾏的是下⾯的表达式。
237 0
|
14天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
30 10
|
1月前
|
存储 编译器 C语言
【C语言】简单介绍进制和操作符
【C语言】简单介绍进制和操作符
152 1
|
1月前
|
存储 编译器 C语言
初识C语言5——操作符详解
初识C语言5——操作符详解
163 0
|
3月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
45 6
|
3月前
|
存储 编译器 C语言
十一:《初学C语言》— 操作符详解(上)
【8月更文挑战第12天】本篇文章讲解了二进制与非二进制的转换;原码反码和补码;移位操作符及位操作符,并附上多个教学代码及代码练习示例
56 0
十一:《初学C语言》—  操作符详解(上)
|
4月前
|
C语言
五:《初学C语言》— 操作符
本篇文章主要讲解了关系操作符和逻辑操作符并附上了多个代码示例
43 1
五:《初学C语言》—  操作符
|
5月前
|
C语言
C语言逻辑操作符的短路问题
C语言逻辑操作符的短路问题
|
5月前
|
编译器 C语言
【C语言】:中移位操作符,位操作符详运算规则详解
【C语言】:中移位操作符,位操作符详运算规则详解
40 1