【C语言】8.C语言操作符详解(1)

文章目录

  • 1.操作符的分类
  • 2.⼆进制和进制转换
  • 3.原码、反码、补码
  • 4.移位操作符
    • 4.1 左移操作符
    • 4.2 右移操作符
  • 5.位操作符:&、|、^、~
    • 5.1 &:按位与
    • 5.2 |:按位或
    • 5.3 ^:按位异或
    • 5.4 ~:按位取反
    • 5.5 例题
      • 例题1
      • 例题2
      • 例题3
      • 例题4


1.操作符的分类

  1. 算术操作符: +-*/%

  2. 移位操作符: << ,>>

  3. 位操作符: &, |, ^

  4. 赋值操作符: =+=-=*=/=%=<<=>>=&=|=^=

  5. 单目操作符: ++--&*+-~sizeof(类型)

  6. 关系操作符: >>=<<===!=

  7. 逻辑操作符: &&||

  8. 条件操作符: ? :

  9. 逗号表达式: ,

  10. 下标引用: []

  11. 函数调用: ()

  12. 结构成员访问: .->


2.⼆进制和进制转换

进制转换的教程网上比比皆是,而且视频看起来肯定比文字清晰。这里就不过多赘述了。

我们需要掌握一下几个:

  1. 2进制10进制
  2. 10进制2进制
  3. 2进制8进制和16进制
  4. 8进制和16进制2进制
  5. 8进制16进制
  6. 16进制8进制

3.原码、反码、补码

整数的2进制表示方法有三种:

  1. 原码

  2. 反码

  3. 补码

有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号位,剩余的都是数值位。

符号位都是用0表示“正”,用1表示“负”。

正整数的原、反、补码都相同。

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。

反码:正数反码和原码一样。

补码:正数补码和原码一样。

负整数的三种表示方法各不相同。

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。(注意符号位)

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码:反码+1就得到补码。


4.移位操作符

只有整数才能运用移位操作符。

4.1 左移操作符

例1:

#include <stdio.h>
int main()
{int num = 10;int n = num<<1;//10补码:  00000000 00000000 00000000 00001010//10<<1补码:0 00000000 00000000 00000000 00010100//这里最前面的0被丢掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= 20
num= 10

例2:

#include <stdio.h>
int main()
{int num = -1;int n = num<<1;//-1原码: 10000000 00000000 00000000 00000001//-1反码: 11111111 11111111 11111111 11111110//-1补码: 11111111 11111111 11111111 11111111
//-1<<1补码:0 11111111 11111111 11111111 11111110//这里最前面的0被丢掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= -2
num= -1

4.2 右移操作符

右移运算分两种:

  1. 逻辑右移:左边用0填充,右边丢弃。

  2. 算术右移:左边用原该值的符号位填充(正数左边补0,负数左边补1),右边丢弃。

    右移是算术右移还是逻辑右移是取决于编译器的。通常采用的都是算数右移。

例1:

#include <stdio.h>
int main()
{int num = -10;//-10原码:10000000 00000000 00000000 00001010//-10反码:11111111 11111111 11111111 11110101//-10补码:11111111 11111111 11111111 11110110//逻辑右移:01111111 11111111 11111111 11111011 |0(这个0被丢弃了)//算术右移:11111111 11111111 11111111 11111011 |0(这个0被丢弃了)//这里采用算数右移//右移补码:11111111 11111111 11111111 11111011//右移反码:10000000 00000000 00000000 00000100//右移原码:10000000 00000000 00000000 00000101--->-5int n = num>>1;printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= -5
num= -10

5.位操作符:&、|、^、~

双目操作符:

  1. &:按位与
  2. |:按位或
  3. ^:按位异或

单目操作符:

  1. ~:按位取反

5.1 &:按位与

有0则0。

#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a & b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a & b补码::00000000 00000000 00000000 00000000-->0printf("n= %d\n", c);return 0;
}

打印:

n= 0

5.2 |:按位或

有1则1。

#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a | b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a | b补码:11111111 11111111 11111111 11111111//a | b反码:10000000 00000000 00000000 00000000//a | b原码:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}

打印:

n= -1

5.3 ^:按位异或

相同为0,不同为1。

#include <stdio.h>
int main()
{int a = 6;// 6的补码:00000000 00000000 00000000 00000110int b = -7;//-7的原码:10000000 00000000 00000000 00000111//-7的反码:11111111 11111111 11111111 11111000//-7的补码:11111111 11111111 11111111 11111001int c = a ^ b;// 6的补码:00000000 00000000 00000000 00000110//-7的补码:11111111 11111111 11111111 11111001//a ^ b补码:11111111 11111111 11111111 11111111//a ^ b反码:10000000 00000000 00000000 00000000//a ^ b原码:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}

打印:

n= -1

5.4 ~:按位取反

按2进制位取反

#include <stdio.h>
int main()
{int a = 0;//0的原码:00000000 00000000 00000000 00000000//~a补码: 11111111 11111111 11111111 11111111//~a反码: 10000000 00000000 00000000 00000000 //~a原码: 10000000 00000000 00000000 00000001-->-1printf("n= %d\n", ~a);return 0;
}

打印:

n= -1

5.5 例题

例题1

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

方法1:

int main() {int a = 3;int b = 5;printf("交换前:a=%d b=%d\n", a, b);a = a + b;b = a - b;a = a - b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

打印:

交换前:a=3 b=5
交换后:a=5 b=3

上面这个方法有点问题,如果a+b的和超过了一个整型数据的存储大小,那么就计算不了了。


方法2:

int main() {int a = 3;int b = 5;printf("交换前:a=%d b=%d\n", a, b);a = a ^ b;b = a ^ b;a = a ^ b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

打印:

交换前:a=3 b=5
交换后:a=5 b=3

为什么呢?

因为异或操作符,相同两个数异或为0。

3^3=0

a^a=0

0异或任何数都为数的本身 。

0^3=3

0^a=a

异或是支持交换率的。


例题2

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

int count_bit_onr(unsigned int n) {int count = 0;while (n) {if ((n % 2) == 1) {count++;}n = n / 2;}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}

输入:

15

打印:

4

也可以这么写:

int count_bit_onr(int n) {int i = 0;int count = 0;for (i = 0; i < 32; i++) {if ((n >> 1) & 1 == 1) {count++;}}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}

输入-1会打印32

这个算法的原理:

-1补码:11111111 11111111 11111111 11111111
1补码: 00000000 00000000 00000000 00000001
-1&1=  00000000 00000000 00000000 00000001

不论-1的补码前面多少个1,只要和1按位与后就只看最后一位是不是1。

然后运用移位操作符,将每一位都和1按位与,统计出一共多少个1。


其实还有更加巧妙地算法:

n=n&(n-1)

例如:n=11

n       = 1011
n-1     = 1010
n&(n-1) = 1010

因为n=n&(n-1),所以现在新的n是1010

n       = 1010
n-1     = 1001
n&(n-1) = 1000

因为n=n&(n-1),所以现在新的n是1000

n       = 1000
n-1     = 0111
n&(n-1) = 0000

从这三次变化里面我们可以看到,我们执行了一次n=n&(n-1),那么n最右面那个1就会消失。把所有的1都去掉后就变成0了。


例题3

写一个代码,判断n是否为2的次方数。

首先我们先看看2的次方数:

000010
000100
001000
010000
100000

可以看出2的次方数里面只有1个1。

if (n & (n - 1) == 0) {printf("yes")
}

例题4

编写代码,将13二进制序列的第五位修改为1,然后改回0。

第5位改成1,第5位就和1或|,其他位都是0。

第5位改为0,第5位就和0与&,其他位都是1。

int main() {int a = 13;//13原码:00000000 00000000 00000000 00001101//13补码:00000000 00000000 00000000 00001101//16补码:00000000 00000000 00000000 00010000//16|13:00000000 00000000 00000000 00011101-->29int n = 5;a = a | (1 << (n - 1));printf("%d\n", a);a &= ~(a << (n - 1));printf("%d\n", a);return 0;
}

打印:

29
13

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

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

相关文章

短视频矩阵系统4年独立开发正规代发布接口源码搭建部署开发

1. 短视频矩阵源码技术开发要求及实现流程&#xff1a; 短视频矩阵源码开发要求具备视频录制、编辑、剪辑、分享等基本功能&#xff0c;支持实时滤镜、特效、音乐等个性化编辑&#xff0c;能够实现高效的视频渲染和处理。开发流程主要包括需求分析、技术选型、设计架构、编码实…

Web前端开发技术、详细文章、(例子)html 列表、有序列表、无序列表、列表嵌套

目录 列表概述 列表类型与标记符号 无序列表 语法&#xff1a; 语法说明&#xff1a; 无序列表标记的 type 属性及其说明 代码解释 有序列表 基本语法 属性说明 1、列表 o1标记的属性 2、列表项li标记的属性 有序列表 o1标记的属性、值 代码解释 列表嵌套 基本…

如何将Qt pro工程文件 改成CMakeLists.txt

Qt pro工程管理文件&#xff0c;本人认为是很好用的&#xff0c;语法简洁易懂&#xff0c;但是只能在QtCreator中使用&#xff0c;想用使用其它IDE比如Clion或者vs&#xff0c;CMakeLists是种通用的选择&#xff0c;另外QtCreator的调试功能跟粑粑一样。 一&#xff0c;思路 …

FreeBSD/Linux下的系统资源监视器排队队

bpytop bpytop 是一个基于 Python 的资源监视器&#xff0c;可以在 FreeBSD 上使用。它提供了对文件写入磁盘、网络、CPU 和内存占用的监视功能。 pkg install bpytop 或者用ports安装 cd /usr/ports/sysutils/bpytop/ make install clean bashtop bashtop 也是一个基于 P…

化简资源分配图判断是否发生死锁

目录 1.资源分配图的概念 2.判断是否发生死锁 1.资源分配图的概念 资源分配图表示进程和资源之间的请求关系&#xff0c;例如下图&#xff1a; P代表进程&#xff0c;R代表资源&#xff0c;R方框中 有几个圆球就表示有几个这种资源&#xff0c;在图中&#xff0c;R1指向P1&a…

C++ RPC ORM 高速解析

支持所有常用编程语 https://capnproto.org/GitHub - capnproto/capnproto: Capn Proto serialization/RPC system - core tools and C library https://capnproto.org/capnproto-c-win32-1.0.2.zip 常用命令&#xff1a; capnp help capnp compile -oc myschema.capn…

java文件上传时给pdf、word、excel、ppt、图片添加水印

前言 在开发的过程中&#xff0c;因为文件的特殊性&#xff0c;需要给pdf、word、excel、ppt、图片添加水印。添加水印可以在文件上传时添加&#xff0c;也可以在文件下载时添加。因为业务的某些原因&#xff0c;文件需要在浏览器预览&#xff0c;如果用户将文件另存为则无法添…

算法与数据结构汇总

基本 数组 字符串 排序 矩阵 模拟 枚举 字符串匹配 桶排序 计数排序 基数排序 回文&#xff1a;中心扩展 马拉车 树上启发式合并 括号 数学表达式 字符串&#xff1a;前后缀分解。 贡献法 分组&#xff1a; 【状态机dp 状态压缩 分组】1994. 好子集的数目 【动态规划】【前缀…

Excel中sum的跨表求和

#实际工作中&#xff0c;一个xlsx文件中会包含多个Excel表格&#xff0c;一般会有“总-分”的关系&#xff0c;如何把分表里的数字汇总到总表里呢&#xff1f; 一般有上图所示的两种表达方式。 可以使用通配符 *&#xff1a;代表任意个数、任意字符&#xff1b; &#xff1f;&…

51单片机的最小系统详解

51单片机的最小系统详解 1. 引言 在嵌入式系统中,51单片机被广泛应用于各种小型控制器和嵌入式开发板中。相信很多人都接触过51单片机,但是对于51单片机的最小系统却了解得不够深入。本文将从振荡电路、电源模块、复位电路、LED指示灯和调试接口五个方面详细介绍51单片机的…

quartz定时任务

Quartz 数据结构 quartz采用完全二叉树&#xff1a;除了最后一层每一层节点都是满的&#xff0c;而且最后一层靠左排列。 二叉树节点个数规则&#xff1a;每层从左开始&#xff0c;第一层只有一个&#xff0c;就是2的0次幂&#xff0c;第二层两个就是2的1次幂&#xff0c;第三…

DOS学习-目录与文件应用操作经典案例-attrib

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 一.前言 DOS系统中的attrib命令是一个用于显示或更改文件&#…

设计模式——职责链(责任链)模式

目录 职责链模式 小俱求实习 结构图 实例 职责链模式优点 职责链模式缺点 使用场景 1.springmvc流程 ​2.mybatis的执行流程 3.spring的过滤器和拦截器 职责链模式 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成…

github设置项目分类

https://www.php.cn/faq/541957.html https://docs.github.com/zh/repositories/working-with-files/managing-files/creating-new-files

什么是回表,如何解决回表问题

下面表中:主键id是聚簇索引&#xff0c;name是辅助索引。 执行这样一条SQL: select name from A where name"s;name字段是有索引&#xff0c;所以MYSQL在通过name进行査询的时候&#xff0c;是需要扫描两颗Btree树的。 第一遍:先通过二级索引定位主键值1。第二遍:根据主键…

免费发布web APP的四个途径(Python和R)

免费发布数据分析类&#x1f310;web APP的几个途径&#x1f4f1; 数据分析类web APP目前用来部署生信工具&#xff0c;统计工具和预测模型等&#xff0c;便利快捷&#xff0c;深受大家喜爱。而一个免费的APP部署途径&#xff0c;对于开发和测试APP都是必要的。根据笔者的经验…

word-形状绘制、smartart、visio

一、人员架构图绘制 小技巧&#xff1a; 1、ctrlshift水平复制 2、点击图形&#xff0c;右键设置为默认形状 3、插入-形状-右键-锁定绘图模式&#xff0c;按esc退出状态 4、插入-形状-新建绘图画布&#xff0c;代替组合问题 画布中存在锚点&#xff0c;便于直线连接 二、s…

网络安全相关面试题(hw)

网络安全面试题 报错注入有哪些函数 updatexml注入 载荷注入 insert注入 updata注入 delete注入 extractvalue&#xff08;&#xff09;注入 注入防御方法 涵数过滤 直接下载相关防范注入文件&#xff0c;通过incloud包含放在网站配置文件里面 PDO预处理,从PHP 5.1开始&…

electron中BrowserWindow的show事件没有触发踩坑记录

class ElectronApi {static mainWindow;//主窗口createWindow() {try {// Create the browser window.this.mainWindow new BrowserWindow({width: 1200,height: 800,minHeight: 800,minWidth: 1200,webPreferences: {preload: preloadPath,// nodeIntegration: true,// conte…

windows怎么复制文件到vmware 中ubantu虚拟机,vmware中的虚拟机怎么联网,NAT参数和DHCP参数。

目录 windows怎么复制文件到vmware 中ubantu虚拟机 vmware中的虚拟机怎么联网 NAT参数和DHCP参数。