C中负数的存储形式 | 位运算符

简介: C中负数的存储形式 | 位运算符

位运算符


C语言中,一共有6个位运算符,优先级由高到低分别是(其中<<>>优先级相同)~ , << , >> , & , ^ , |

分别说明:

位运算符 作用
~ 按位取反,1变为0, 0变为1
<< 左移,最高位舍,最低位补0,例: 0000 0000 0000 1001 左移1位, =>0000 0000 0001 0010
>> 右移 , 最低位舍,最高位补0, 例:0000 0000 0000 1001 右移一位 =>0000 0000 0000 0100 ,
& 按位与,只有当其同为1时,才为1,否则为0
^ 按位异或,相同为0,不同为1。只有两个不同时,才为1,否则为0
| 按位或,有1为1,没有为0,只要两者中存在一个1,就为1,两个都是1也为1,否则为0

注意: 1001>>1 并不等于100,这里的1001表示的是10进制数,想表示二进制数1001,需加上前缀0b,即0b1001。


  • M<<N,表示将M左移N位,所得的数相当于,M乘以2的N次方
  • 例: 要得到2的3次方, 1<<3效率最高,而不是2 * 2 * 2或者 pow(2,3)
  • 类似的,M>>N,表示将M右移N位,所得的数相当于,M除以2的N次方,整数与整数相除结果也为整数,注意。
  • 例: 9>>1 , 结果为9/2等于 4
  • 如果整数a,b相等,可得到 a^b等于 0 . 即 if(a!=b)等价于if(a ^ b)
  • 大小写转换: x^=32 , 如输入A(65),转换为a(97); 如输入z(122),转换为Z(90)
  • 实例:将输入的字符串,大写转小写,小写转大写
int main(){
    char str[10], *p;
    p = str;
    scanf("%s", p);
    for (int i = 0; str[i] != '\0'; i++)
        str[i] ^= 32;
    printf("%s", p);
    return 0;
}

负数的存储形式


按编译系统不同,整形在C中占用2字节或4字节, 一字节8位 .

以下讨论的按2字节举例: 只讨论整形 .

说负数的存储形式前,先说正数的存储形式 , 正数的存储形式,就是其二进制.

例:1 的存储形式,0000 0000 0000 0001

9的存储形式: 0000 0000 0000 1001

而 负数的存储形式是其绝对值的存储形式按位取反,再加一 .

此处按4字节算:
整数1的存储方式:
  0000 0000,0000 0000,0000 0000,0000 0001
整数 -1 的存储方式:
  0000 0000,0000 0000,0000 0000,0000 0001
  按位取反:
  1111 1111,1111 1111,1111 1111,1111 1110
  再加上1:
  1111 1111,1111 1111,1111 1111,1111 1111
  所以整数 -1 的存储方式为:
    1111 1111,1111 1111,1111 1111,1111 1111

案例

#include <stdio.h>

int main(){
    int x = M;
    printf("%d",~x);
    return 0;
}

M为一个整数常量 , 输出的值始终为 -(M+1),如当M为1时,输出打印 -2

为啥?

首先,就要说到C语言中,负数的存储形式:负数的存储形式是其绝对值的二进制形式 按位取反再加一


例: -1 (如整形按两个字节计算)


其绝对值 1 的二进制形式: 0000 0000 0000 0001


按位取反 ~: 1111 1111 1111 1110


再加一: 1111 1111 1111 1111


所以-1在内存中的存储形式为: 1111 1111 1111 1111


内存中,首位(最高位)为0,表示一个正数,为1表示一个负数。


所以,当遇到存储形式为:0000 0000 0000 0001 的, 首先看其最高位是0(是正数)还是1(还是负数)。


如是 0 :则直接按二进制转十进制, 0000 0000 0000 0001的十进制便是 1,所以其表示的也是1。


如存储形式为:1000 0000 0000 0001,最高位为1,便不可直接按二进制转十进制得到 32769,


因为最高位为1,代表负数,而负数的存储方式与正数不同,不可直接转化为十进制,需先减一,再按位取反,回推。


减一: 1000 0000 0000 0000


按位取反:0111 1111 1111 1111


再转十进制:32767


又因首位是1,表示负数,所以1000 0000 0000 0001所表示的数是 -32767,并不是-1,也不是32769。


相关文章
|
存储 编译器 C语言
STM32开发 -- Keil基本使用
STM32开发 -- Keil基本使用
1449 0
|
安全
[UDS] --- TesterPresent 0x3E
[UDS] --- TesterPresent 0x3E
527 1
物联网卡:带你快速了解物联网卡充值失败的原因
物联网卡充值失败可能由多种原因引起,下面是一些常见的原因及相应的操作建议,以帮助您解决问题:
|
Web App开发 Linux Windows
解决Markdown文件上传至CSDN无法显示本地图片问题-白嫖版,分享给别人的md文件图片不显示的解决方案
解决Markdown文件上传至CSDN无法显示本地图片问题-白嫖版,分享给别人的md文件图片不显示的解决方案
633 3
Byte 高位/低位简介绍(大端格式/小端格式)
Byte 高位/低位简介绍(大端格式/小端格式)
1762 1
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
6286 4
|
存储 算法 安全
MD5哈希算法:原理、应用与安全性深入解析
MD5哈希算法:原理、应用与安全性深入解析
|
设计模式 Java 程序员
拜托!别再滥用 != null 判空了!!——优化你的代码,提升开发效率
【8月更文挑战第20天】在软件开发的世界里,null 值的存在如同一把双刃剑,既提供了灵活性,也带来了复杂性。而!= null 的判空操作,几乎成了每个程序员日常编码中的“标配”。然而,过度依赖这种简单直接的判空方式,往往会导致代码可读性下降、逻辑冗余、甚至引入难以察觉的bug。今天,我们就来探讨一下如何优雅地减少或避免滥用!= null判空,从而提升代码质量和开发效率。
399 3
|
机器学习/深度学习 并行计算 算法
【计算机视觉+CNN】keras+ResNet残差网络实现图像识别分类实战(附源码和数据集 超详细)
【计算机视觉+CNN】keras+ResNet残差网络实现图像识别分类实战(附源码和数据集 超详细)
477 1
|
存储 缓存 程序员
C++内存管理:避免内存泄漏与性能优化的策略
C++内存管理涉及程序稳定性、可靠性和性能。理解堆和栈的区别至关重要,其中堆内存需手动分配和释放。避免内存泄漏的策略包括及时释放内存、使用智能指针和避免野指针。性能优化策略则包括减少内存分配、选用合适数据结构、避免深拷贝及缓存常用数据。通过这些最佳实践,可提升C++程序的效率和质量。