[转]c语言int表示范围以及移位运算符

本文介绍了计算机系统中数值的补码表示方法及其与原码的转换过程,并详细解释了正数与负数补码的特点。此外,还探讨了int类型的表示范围及移位运算符的使用规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在计算机系统中,数值一律用补码来表示(存储)。 


主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补 
码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。 
2、补码与原码的转换过程几乎是相同的。 
数值的补码表示也分两种情况: 
(1)正数的补码:与原码相同。 
例如,+9的补码是00001001。 
(2)负数的补码:符号位为1,其余位为该数绝对值的原码按位取反;然后整个数加1。 
例如,-7的补码:因为是负数,则符号位为“1”,整个为10000111;其余7位为-7的绝对值+7的原码 
0000111按位取反为1111000;再加1,所以-7的补码是11111001。 
已知一个数的补码,求原码的操作分两种情况: 
(1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。 
(2)如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:符号位为1,其余各位取 
反,然后再整个数加1。 
例如,已知一个补码为11111001,则原码是10000111(-7):因为符号位为“1”,表示是一个负 
数,所以该位不变,仍为“1”;其余7位1111001取反后为0000110;再加1,所以是10000111。 


 

刚刚看到的几个小基础知识,记录一下:
在int型为32位的硬件环境中,int的表示范围是:-2的31次方  到   2的31次方减1
原因:因为int是带符号类型,所以最高位为符号位,于是最大表示的正数是:01111111 11111111 11111111 11111111,也就是2的31次方减1。
再来看最小值,-2的31次方的原码表示为10000000 00000000 00000000 00000000,此时最高位的数字既代表符号,也代表数值。求它的补码,所得结果为10000000 00000000 00000000 00000000。同样也是最高位既代表符号又代表数值,也就是说-2的31次方的原码和补码是相同的。
接着试试-2的31次方减1,它的原码为(假设先不考虑溢出)11111111 11111111 11111111 11111111,求反加1之后为10000000 00000000 00000000 00000001,变成了-1。所以,int的表示范围是: 
-2的31次方  到   2的31次方减1

然后是移位运算符:

 

 

  1. int i = 1;  
  2. i = i << 2;  


这是把i左移两位,左移的规则只记住一点:丢弃符号位,0补最低位!
如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模。如对int型移动33位,实际上只移动了33%32=1位。
右移有两种,算术右移(带符号)>>和逻辑右移(不带符号)>>>。
算术右移符号位不变,左边补上符号位如: 1000 1000 >> 3 为 1111 0001
逻辑右移符号位一起移动,左边补上0如:1000 1000 >>> 3 为 0001 0001
最后,移位的位数不能超过数据的大小,不能小于0。

 

### C语言移位运算符的使用教程 #### 1. 移位运算符简介 C语言中的移位运算符用于对整数类型的变量执行位级操作。它主要包括两种基本形式:左移(`<<`)和右移(`>>`)。通过这些运算符,程序员可以直接操控数据的二进制表示。 - **左移运算符 (`<<`)** - 将操作数的所有比特向左移动指定数量的位置。 - 右侧空出的部分会补零[^1]。 - **右移运算符 (`>>`)** - 将操作数的所有比特向右移动指定数量的位置。 - 若为有符号类型,则左侧空出部分由原最高有效位决定;若是无符号类型,则左侧空出部分填入0[^3]。 #### 2. 运算规则详解 ##### (a) 左移运算符 `<<` 当一个数值被左移n位时,相当于该数值乘以\(2^n\)(假设不发生溢出的情况下),即每左移一位就等于将其值加倍。例如: ```c int a = 8; // 原始值为8,在内存中存储为 00001000(二进制) int b = a << 1; // 结果b=16, 即把a的每一位都往左边挪了一格变成 00010000 ``` 上述例子展示了如何利用左移来快速实现幂次方计算或者简单的倍增效果[^1]。 ##### (b) 右移运算符 `>>` 对于正数而言,每次右移都会使数值缩小一半(向下取整)。而对于负数来说,其行为取决于具体平台以及编译器实现方式——某些情况下可能会保留原始符号位并复制到高位上形成所谓的“算术右移”,而其他时候可能只是简单地插入零作为新的高阶位从而造成逻辑上的变化[^2]。 下面是一个关于带符号整型的例子: ```c signed int c = -16; // 负十六对应的二进制可能是...11110000 signed int d = c >> 1; // 如果采用算术右移,d=-8(...11111000),否则d=不同结果依赖环境设定 ``` 值得注意的是,如果希望无论何种情况都能得到统一的结果,则应考虑使用无符号版本的数据类型来进行此类操作[^3]: ```c unsigned int e = 16; unsigned int f = e >> 1; // 不论e原本为何种状态,f始终等于八因为只关注绝对大小关系而不关心正负号影响 ``` #### 3. 实际应用案例分析 以下是几个实际应用场景下的代码片段说明: ###### 计算2的N次幂 可以通过连续左移的方式高效求解某个固定基数底数的不同指数幂值: ```c #include<stdio.h> void main(){ int powerOfTwo(int n); printf("%d\n",powerOfTwo(5)); // 输出应该是32 } // 函数定义区 int powerOfTwo(int n){ return 1<<n ; } ``` 这里我们创建了一个名为`powerOfTwo()`的小函数用来返回给定参数所代表的那个特定位置上的权重贡献度量单位长度之后再累加起来构成最终目标产物[^1]. ###### 判断奇偶性优化方法 由于任何偶数最低位必定为0,因此只需检测最后一位即可得知当前数字是否可除尽两: ```c bool isEven(unsigned long num){ return !(num & 1u); } /* 或者更进一步简化 */ #define IS_EVEN(n)((!(n&1))==true) if(IS_EVEN(someNumber)){ puts("It's even!"); }else{ puts("Odd one here."); } ``` 此技巧不仅限于基础判断任务之中还可以扩展至更多复杂场景比如循环迭代过程中动态调整步幅等等[^3]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值