浅析位运算符(左移、右移、与、或、异或)

news2024/11/24 22:28:30

        C语言是一种很奇妙的语言,它既有高级语言的特点,又有低级语言的特点,支持位运算让它更方便于硬件编程。

一、左移运算符(<<)

        左移运算就是将一个二进制位的操作数按指定位数整体向左移位,移出位被丢弃(是否丢弃也不一定,得看接收结果的数据类型范围),右边的空位一律补0。

语法:x << n,其中 x 是要移动的数字,n 是要移动的位数。

关联的数学公式:位左移结果 = 要移动的数字 * 2的n次方(n 是要移动的位数)。该公式不是总有效啊!

1、正数左移举例:

完整代码在后面。

这里我们用char类型,因为它范围是1个字节,8bit位,方便查看结果。

        char ch = 10;                 // 00001010
        // 左移1位
        char r1 = ch << 1;         // 00010100
        printf("10 << 1 = %d\n", r1);    // 20 (10*2的1次方)

结果如下:

        // 左移2位
        char r2 = ch << 2; // 00101000
        printf("10 << 2 = %d\n", r2);    // 40 (10*2的2次方)
        // 左移3位
        char r3 = ch << 3; // 01010000
        printf("10 << 3 = %d\n", r3);    // 80 (10*2的3次方)


      结果如下:

==== 下面是重点 ====

左移4位-->关键地方到了,因为左移4位后最左边是1了,也就是说符号位为1,可能变负数了。
        char r4 = ch << 4; // 10100000,转换为十进制为 -32,但真的是-32吗?
        printf("10 << 4 = %d\n", r4);

结果如下:

        答案是-96,正数左移真的有可能变成负数了,但为什么不是-32呢。
        因为数值在内存中存储的补码,正数的原码、反码、补码是一样的。负数的补码=原码取反+1。
        我们对内存中的数左移时实际上都是对补码进行左移,实际取值时还要转换为原码的。
        10100000,符号位是1,负数,取原码时要先减去1,再取反才行。
             10100000
          -                1    
          -----------------
              10011111 
     取反  11100000 -> -96
        原码、反码、补码不懂的可以看我以前写的文章。
        10 << 4 一定是负数吗?看下面代码
        short r44 = ch << 4;
        printf("10 << 4 = %d\n", r44);    // 160 (10*2的4次方)

怎么样,没变负数吧,也就是说左边移动的4位并没有被舍弃,这是因为我们用short类型来接收的,该类型为2个字节,你左移8位都能完整接收,更何况仅仅是左移4位了,因此不会舍弃。

完整代码如下:

int main()
{
	char ch = 10;
	
	// 左移1位
	char r1 = ch << 1;
	printf("10 << 1 = %d\n", r1);

	// 左移2位
	char r2 = ch << 2;
	printf("10 << 2 = %d\n", r2);

	// 左移3位
	char r3 = ch << 3;
	printf("10 << 3 = %d\n", r3);

	// 左移4位
	char r4 = ch << 4;
	printf("10 << 4 = %d\n", r4);

	// 左移4位
	short r44 = ch << 4;
	printf("10 << 4 = %d\n", r44);


	return 0;
}
2、负数左移举例:

        注意:负数在内存中存储的是补码,对补码进行左移,再换算成原码才是我们要的结果。挺闹心的啊!但没办法,这不是我们能决定的。

        char ch = -10; // 原码10001010 --> 补码 11110110 (负数要看补码啊!!!!!!!!!)
        // 左移1位
        char r1 = ch << 1;    // 补码11101100 --> 原码 10010100
        printf("-10 << 1 = %d\n", r1);    // -20 (-10*2的1次方)

结果如下:

        // 左移2位
        char r2 = ch << 2;    // 补码 11011000 --> 原码 10101000
        printf("-10 << 2 = %d\n", r2);    // -40 (-10*2的2次方)
        // 左移3位
        char r3 = ch << 3;    // 补码 10110000 --> 原码 11010000
        printf("-10 << 3 = %d\n", r3);    // -80 (-10*2的3次方)

结果如下:

======== 重点又到了 ========

        左移4位-->关键地方又到了,因为左移4位后最左边是0了,也就是说符号位为0,可能变正数了。
        char r4 = ch << 4;    // 补码 01100000 --> 原码 01100000
        printf("-10 << 4 = %d\n", r4);    // 96 (数学公式不好用了)

结果如下:

        -10 << 4 一定是正数吗?看下面代码
        short r44 = ch << 4;
        printf("-10 << 4 = %d\n", r44);    // -160 (-10*2的4次方)

结果如下:


        怎么样,没变正数吧,也就是说左边移动的4位并没有被舍弃,这是因为我们用short类型来接收的,该类型为2个字节,你左移8位都能完整接收,因此不会舍弃。

完整代码如下:

int main()
{
	char ch = -10;
	
	// 左移1位
	char r1 = ch << 1;
	printf("-10 << 1 = %d\n", r1);

	// 左移2位
	char r2 = ch << 2;
	printf("-10 << 2 = %d\n", r2);

	// 左移3位
	char r3 = ch << 3;
	printf("-10 << 3 = %d\n", r3);

	// 左移4位
	char r4 = ch << 4;
	printf("-10 << 4 = %d\n", r4);

	// 左移4位
	short r44 = ch << 4;
	printf("-10 << 4 = %d\n", r44);

	return 0;
}

    总结:左移运算时正数可能会变负数,负数也可能会变正数,左移的位数也未必舍弃,就看你用什么类型接收它,这个要注意啊。

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

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

相关文章

【力扣】记录一下竞赛分上 Knight

记录一下力扣上 Knight 力扣的题还是相对来说比较简单的&#xff0c;前两个月写的题多一点&#xff0c;后面几乎都是只做了每日一题&#xff0c;感觉正常来说刷个两三个月的题水平就差不多够了&#xff0c;甚至在我才刷半个月的时候就可以做三题了&#xff0c;排名和现在差不多…

手机上菜谱记录簿在哪 用备忘录放大看菜谱更清晰

作为一个热爱生活的现代人&#xff0c;我深知健康饮食的重要性。然而&#xff0c;每当我想亲手为自己和家人烹饪美食时&#xff0c;厨艺的不精常常让我望而却步。好在互联网时代&#xff0c;网上搜罗的各式菜谱成了我的救星。但问题是&#xff0c;每次做菜时都得反复查找&#…

docker运行redis,jdk,nginx

Redis 1.查询redis [rootlocalhost ~]# docker search redis NAME DESCRIPTION STARS OFFICIAL redis Redis is an open source key-value store that… 12620 …

解决vue 2.6通过花生壳ddsn(内网穿透)实时开发报错Invalid Host header和websocket

请先核对自己的vue版本&#xff0c;我的是2.6.14&#xff0c;其他版本未测试 起因 这两天在维护一个基于高德显示多个目标&#xff08;门店&#xff09;位置的项目&#xff0c;由于高德要求定位必须使用https服务&#xff0c;遂在本地无法获取到定位坐标信息&#xff0c;于是…

因谷歌Play Store审核超过7天和联系他们的方式

三种联系他们的方式 1.让他们打电话过来 英语好不好没关系&#xff0c;主要是他们讲着一口浓厚的印度口音英语&#xff0c;很难听懂 2.在线实时聊天沟通 可以选择英文、中文、但是英文肯定容易约上 3.发送邮件 回复太慢了&#xff0c;1-2天回复你一次 传送门&#xff1…

时间轮设计

目录 基本概念 函数定义 函数实现与测试 测试1结果如下 测试2结果如下 基本概念 时间轮 是一种 实现延迟功能&#xff08;定时器&#xff09; 的 巧妙算法。如果一个系统存在大量的任务调度&#xff0c;时间轮可以高效的利用线程资源来进行批量化调度。把大批量的调度任务…

【算法与数据结构】377、LeetCode组合总和 Ⅳ

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题明面上说是组合&#xff0c;实际上指的是排列。动态规划排列组合背包问题需要考虑遍历顺序。 d p …

[Python] opencv - 如何使用VideoCapture类进行摄像头视频捕获并显示

VideoCapture类介绍 OpenCV-Python 中的 VideoCapture 类是一个用于捕获视频的类&#xff0c;它可以从摄像头、视频文件或者设备上捕获视频。主要方法有&#xff1a; class VideoCapture:# Functions_typing.overloaddef __init__(self) -> None: ..._typing.overloaddef _…

性能篇:解密Stream,提升集合遍历效率的秘诀!

大家好&#xff0c;我是小米&#xff0c;一个热爱技术分享的小伙伴。今天我们来聊一聊 Java 中的 Stream&#xff0c;以及如何通过 Stream 来提高遍历集合的效率。 什么是Stream&#xff1f; 在开始深入讨论之前&#xff0c;我们先来了解一下什么是 Stream。 Stream 是 Java…

2024-01-19(SpringCloudThreadLocal)

1.Seata的TC服务注册到Nacos注册中心当中 2.Seata为我们提供了AT&#xff0c;TCC&#xff0c;SAGA&#xff0c;XA事务解决方案。 3.XA规范是一种分布式事务处理标准&#xff0c;XA规范描述了全局的TM与局部的RM之间的接口&#xff0c;几乎所有的主流的数据库都对XA规范提供了…

JavaScript递归函数如何匹配上下级id和pid的数据(for...of,foreach.reduce)

目录 一、for...of 二、forEach 三、reduce 递归函数是一种在编程中常用的方法&#xff0c;用于解决一些需要重复操作的问题。在JavaScript中&#xff0c;递归函数可以用来匹配上下级id和pid的数据结构&#xff0c;例如树形结构或者父子关系的数据。 一、for...of 首先…

【网络安全 -> 防御与保护】专栏文章索引

为了方便 快速定位 和 便于文章间的相互引用等 作为一个快速准确的导航工具 网络安全——防御与保护 &#xff08;一&#xff09;.信息安全概述

《移动通信原理与应用》——QAM调制解调仿真

目录 一、QAM调制与解调仿真流程图&#xff1a; 二、仿真结果&#xff1a; 三、Matlab仿真程序代码如下&#xff1a; 一、QAM调制与解调仿真流程图&#xff1a; QAM调制仿真流程图&#xff1a; QAM解调仿真流程图&#xff1a; 二、仿真结果&#xff1a; &#xff08;1&…

20.云原生之GitLab CICD实战

云原生专栏大纲 文章目录 GitLab RunnerGitLab Runner 介绍Gitlab Runner工作流程 Gitlab集成Gitlab RunnerGitLab Runner 版本选择Gitlab Runner部署docker-compose方式安装kubesphere中可视化方式安装helm方式安装 配置gitlab-runner配置gitlab-ci.ymlgitlab-ci.yml 介绍编写…

OpenHarmony当前进展和未来趋势

操作系统自20世纪50年代诞生&#xff0c;经历了从专用操作系统到通用操作系统的转变。整体可以将操作系统的发展历史分为3个阶段&#xff1a;PC时代、移动互联网时代、万物互联时代。 PC时代主要以计算机为主&#xff0c;用户规模从1970年的10亿增长到1990年的30亿。这一时代诞…

TensorFlow框架(6)之RNN循环神经网络详解

1. RNN循环神经网络 1.1 结构 循环神经网络&#xff08;recurrent neural network&#xff0c;RNN&#xff09;源自于1982年由Saratha Sathasivam 提出的霍普菲尔德网络。RNN的主要用途是处理和预测序列数据。全连接的前馈神经网络和卷积神经网络模型中&#xff0c;网络结构都…

牛客周赛 Round 20 解题报告 | 珂学家 | 状压DP/矩阵幂优化 + 前缀和的前缀和

前言 整体评价 这场比赛很特别&#xff0c;是牛客周赛的第20场&#xff0c;后两题难度直线飙升了。 前四题相对简单&#xff0c;E题是道状压题&#xff0c;历来状压题都难&#xff0c;F题压轴难题了&#xff0c;感觉学到了不少。 A. 赝品 先求的最大值 然后统计非最大值的个…

2008年苏州大学837复试机试C/C++

2008年苏州大学复试机试 题目 编写程序充成以下功能: 一、从键盘上输入随机变量x的 10个取样点。X0&#xff0c;X1—X9 的值; 1、计算样本平均值 2、判定x是否为等差数列 3、用以下公式计算z的值(t0.63) 注。请对程序中必要地方进行注释 补充&#xff1a;个人觉得这个题目回忆…

【算法与数据结构】279、LeetCode完全平方数

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题可以抽象成一个完全背包问题。完全平方数是物品&#xff0c;n为背包最大重量。本题和【算法与数据…

docker 安装手册

docker 安装手册 第一步卸载旧的docker (如果安装过Docker否则跳过此步) 以防万一最好执行一遍 yum -y remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 第二步&#xff0c;安装相关…