深入理解原码、反码、补码(结合C语言)

一、引出问题

在学习C语言单目操作符中~按位取反的过程中,对这样一段代码的结果产生了疑惑:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main() {
    int a = 0;
    int b = ~a;·//按位取反
    printf("%d\n", b);
    return 0;
}

输出结果:
-1

首先,int整型占4个字节,0化为二进制形式为00000000 00000000 00000000 00000000这样,按位取反后是11111111 11111111 11111111 11111111,化为十进制不应该是一个很大的负数吗,而输出结果却为-1。

之后我查阅资料才发现,我忘记了负数在计算机内存中是以补码的方式存储和进行运算的。于是我又将原码、反码、补码相关的知识复习了一遍,温故而知新,重新总结如下。

二、深入理解原码、反码、补码

在计算机中,数字的二进制位的第一位是符号位,0为正,1为负

首先要明白,原码、反码、补码是计算机用于表示带符号整数的三种编码方式

  1. 原码:原码最高位为符号位,其余位为数值绝对值的二进制值,如5的原码是0000 0101,-5的原码是1000 0110。原码表示最直观,但在进行加减法运算时存在问题,如5+(-5)理论上等于0,但原码相加得1000 1011并不是0000 0000
  2. 反码:正数的反码与原码相同,负数的反码是将原码符号位不变,其余位按位取反。如5的反码即原码0000 0101,-5的反码为1111 1010。
    引入反码是为了更好的解决二进制正数与负数间的加减法问题,如5+(-6)即0000 0101 + 1111 1001 = 1111 1110(反码),转为原码即符号位不变,其余位取反,得1000 0001,正好是-1。
    但反码仍然存在溢出和零的表示问题,如-5+6,即1111 1010 + 0000 0110 => 溢出得0;-5+5即1111 1010 + 0000 0101 = 1111 1111(反码),转为原码即1000 0000,这就与0000 0000的0的原码表示方式存在冲突,一个数总不能有两种表示方法吧。于是就有了下面的补码。
  3. 补码:正数的补码与原码相同,负数的补码是将负数的原码符号位不变,其余位取反后再加1(即负数的反码+1)。如5的补码即原码0000 0101,-5的补码为1111 1011。
    补码的引用很好的解决了加减法和0的表示问题,还能够自然地处理溢出,下面验证一下:
    • -6+5,即1111 1010 + 0000 0101 = 1111 1111,转为原码(补码-1,符号位不变,其余位取反)得1000 0001,即-1,没毛病。
    • -5+6,即1111 1011 + 0000 0110 => 溢出且得0000 0001,正数,即原码本身,得1,没毛病。
    • -5+5,即1111 1011 + 0000 0101 => 溢出且得0000 0000,与0的原码表示相同,没毛病。
      由此可见,在计算机中,补码是最常见和最有效的带符号整数表示方式。
      因此,在计算机中,带符号的整数在内存中存储的是其二进制的补码

那么这就可以理解结果为什么为-1而不是一个很大很大的负数,以上代码的计算过程如下:

//a=0的补码(也是原码)
00000000 00000000 00000000 00000000
//~取反运算得到b的补码
11111111 11111111 11111111 11111111
//补码-1
11111111 11111111 11111111 11111110
//符号位不变,按位取反得到原码
10000000 00000000 00000000 00000001

即得到打印出来的结果为-1

终于,破案了~

三、关于原码、反码、补码之间的转换

1.对于正数,原码 = 反码 = 补码
2.对于负数,此图足以:
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用trigger-forward跨流水线传递参数

参考文档&#xff1a;https://docs.gitlab.com/ee/ci/yaml/#triggerforward 今天给大家介绍一个gitlab CI/CD的关键字 - forward&#xff0c;该关键字是一个比较偏的功能&#xff0c;但同时也是一个很实用的功能&#xff0c;我们通过在gitlab的ci文件中使用forward关键字&#…

二叉树遍历及应用

文章目录 前言构建二叉树前序遍历中序遍历后序遍历二叉树的结点个数二叉树的叶节点个数二叉树的高度二叉树第K层结点个数 前言 二叉树的遍历及应用主要是运用了递归、分治的思想。在这一篇文章&#xff0c;小编将介绍二叉树的前序遍历、中序遍历、后序遍历&#xff0c;求二叉树…

renpy-renpy对话内容汉化

文章目录 前言思路实现1,提取对话内容2,汉化对话内容文件3,修改gui文件,使得renpy游戏支持中文显示 前言 最近下载了一些renpy视觉小说内容,发现对话都为英文,因此我在想能否提取出这些对话然后汉化后再封装回原文件,将其汉化 当然汉化过程是机器翻译,汉化其他语言同理,大概5分…

根文件系统构建-对busybox进行配置

一. 简介 本文来学习 根文件系统的制作中&#xff0c;关于 busybox的配置。 本文继上一篇 busybox中文支持的设置&#xff0c;地址如下&#xff1a; 根文件系统构建-busybox中文支持-CSDN博客 二. 根文件系统构建-busybox配置 1. 配置 busybox 与我们编译 Uboot 、 Lin…

阵列信号处理---频率-波数响应和波束方向图

波束延迟求和器 阵列是由一组全向阵元组成&#xff0c;阵元的位置为 p n p_n pn​&#xff0c;如下图所示&#xff1a; 阵元分别在对应的位置对信号进行空域采样&#xff0c;这样就产生了一组信号信号为 f ( t , p ) f(t,p) f(t,p),具体表示如下&#xff1a; f ( t , p ) [ f…

详解递归锁,以及递归锁与其他同步机制的区别

什么是递归锁 递归锁是一种多线程同步机制&#xff0c;用于解决线程在多次获取同一个锁时产生死锁的问题。在递归锁中&#xff0c;同一个线程可以多次获取同一个锁&#xff0c;而不会造成死锁。 递归锁具有两个主要操作&#xff1a;上锁&#xff08;lock&#xff09;和解锁&a…

OpenCV技术应用(5)— 将一幅图像均分成4幅图像

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教你如何将一幅图像均分成4幅图像&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.实现代码 &#x1f680;1.技术介绍 如果将下图…

【论文阅读】基于隐蔽带宽的汽车控制网络鲁棒认证(三)

文章目录 第六章 通过认证帧定时实现VulCAN的非once同步6.1 问题陈述6.2 方法概述6.3 动机和缺点6.3.1 认证帧定时隐蔽通信6.3.2 VulCAN 的 vatiCAN后端 Nonce同步的应用【这块是一点没看明白】 6.4 设计与实现6.4.1发送方6.4.2 接收方6.4.3 设计参数配置6.4.4 实现 6.5 安全注…

linux复习笔记06(小滴)

演练企业静态ip地址配置过程 我们有时候会发现&#xff0c;在使用虚拟机的时候&#xff0c;如果使用远程连接工具&#xff0c;我们会发现&#xff0c;有时候连接不上去&#xff0c;但是我们去用ifconfig去查看的时候&#xff0c;我们发现是ip地址换了。所以往往我们也需要去固…

SVN下载使用和说明

一、SVN <1>SVN的简介 1、svn是什么&#xff1f; 2、作用 3、基本操作 <2>服务器端的软件下载和安装 1、下载 2、查看环境变量 3、验证安装是否成功 <3>创建项目版本库 1、创建项目版本库&#xff08;svn reponsitory&#xff09; 2、svn版本控制文件说明…

BUUCTF [GXYCTF2019]SXMgdGhpcyBiYXNlPw== 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件&#xff0c;解压得到flag.txt文件。 解题思路&#xff1a; 1、打开flag.txt文件&#xff0c;内容如下。 Q2V0dGUgbnVpdCwK SW50ZW5hYmxlIGluc29tbm…

7.C转python

1.对字典的各种操作都是对键来进行的 2.关于字典的遍历操作 例: 还可以这样遍历 所以生成了一个固定模版来遍历字典: 例: 那两个名字可以换 例: 3.合法key的类型: 要求可哈希 在python中,专门提供了一个hash()函数来计算哈希值 例: 有的类型是不能计算哈希的,如:列表,字…

Fabric:创建应用通道

搭建自定义网络可以参考文章&#xff1a; https://blog.csdn.net/yeshang_lady/article/details/134113296 1 创建通道 网络搭建完成之后&#xff0c;就可以开始创建通道了。Fabric V2.5.4中可以在不创建系统通道的情况下直接创建应用通道。 1.1 修改配置文件 先创建配置文…

QProcess 启动 进程 传参数 启动控制台进程 传参

目录 QProcess 启动外部程序的两种方式 依赖式 分离式&#xff1a; 启动进程前的预处理 设置启动路径 设置启动命令参数 设置启动工作目录 设置启动所需环境&#xff1a; 启动的状态 code smple: QProcess 控制台进程 QProcess启动控制台不显示窗口 注意&#xff1a;…

一、服务器准备

本案例使用VMware Workstation Pro虚拟机创建虚拟服务器来搭建Linux服务器集群&#xff0c;所用软件及版本如下&#xff1a; Centos7.7-64bit 1、三台虚拟机创建 第一种方式&#xff1a;通过iso镜像文件来进行安装(不推荐) 第二种方式&#xff1a;直接复制安装好的虚拟机文…

Linux多核飞控

Linux多核飞控是一种基于多核处理器构建的飞控系统&#xff0c;用于控制飞行器的飞行。这种飞控系统使用Linux操作系统作为主要的控制平台&#xff0c;可以支持多个处理器核心同时工作&#xff0c;以实现更高的性能和更快的响应速度。 Linux通常用于具有较高计算量和较大内存需…

ffmpeg 任意文件读取漏洞/SSRF漏洞 (CVE-2016-1897/CVE-2016-1898)

漏洞描述 影响范围 FFmpeg 2.8.x < 2.8.5FFmpeg 2.7.x < 2.7.5FFmpeg 2.6.x < 2.6.7FFmpeg 2.5.x < 2.5.10 漏洞环境及利用 搭建docker环境 访问8080端口看到上传界面 由于vulhub并没有讲述该漏洞如何复现&#xff0c;我们需要进入环境查看源码 <?php if(!…

vue3使用vue-router路由(路由懒加载、路由传参)

vue-router 是 vue的一个插件库 1. 专门用来实现一个SPA单页面应用 2 .基于vue的项目基本都会用到此库 SPA的理解 1) 单页Web应用&#xff08;single page web application&#xff0c;SPA&#xff09; 2) 整个应用只有一个完整的页面 3) 点击页面中的链接不会刷新页面, 本…

对于Kotlin DSL的简单解析与使用

DSL(领域特定语言)是Kotlin所带来的强大语法特性之一&#xff0c;也是Java中所不存在的功能&#xff0c;JetBrain也基于DSL开发出了众多的开源库&#xff0c;Kotlin的开发者可以使用DSL来重构许多已有的代码&#xff0c;甚至有可能做到彻底抛弃HTML&#xff0c;XML&#xff0c;…

【智能家居】一、工厂模式实现继电器灯控制

用户手册对应的I/O 工厂模式实现继电器灯控制 代码段 controlDevice.h&#xff08;设备设备&#xff09;main.c&#xff08;主函数&#xff09;bathroomLight.c&#xff08;浴室灯&#xff09;bedroomLight.c&#xff08;卧室灯&#xff09;restaurantLight.c&#xff08;餐厅…