C语言关于位<<和>>运算符

int类型整数占四个字节,所能表示的范围为  -2147483648~~2147483647。假如当数据溢出的时候,有趣的事情发生了

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int a=0x80000000;//所能表示最小数 -2147483648
    int b=0x7fffffff;//表示的最大数    2147483647 
    printf("%d %d\n",a-1,b+1);
    
    return 0;
}

输出为    2147483647   -2147483648

也就是说最小数溢出后是最大数,最大数溢出后是最小数。可是为什么呢?这和计算机里面补码运算有关,如下:

 -2147483648十六进制:0x80000000

 -2147483648二进制补码  0b10000000,00000000,00000000,00000000

                   -1二进制补码  0b11111111,    11111111,    11111111,     11111111

                                相加   0b01111111,     11111111,    11111111,     11111111

所以结果是最大值    2147483647,同理可以求得最大值溢出后是最小值。 

知道了这个后,我们继续讨论<<    >>运算。



左移

    当按位左移 m位时候,右端补 m 个 0,相当于乘上 2^m ,左移会引起符号位改变。

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int a=0xffffffff;
    int b=0x7fffffff;
    for(int i=1;i<33;i++)
    printf("%2d %12d %12d\n",i,a<<i,b<<i);
    return 0;
}

输出列表

 1           -2           -2
 2           -4           -4
 3           -8           -8
 4          -16          -16
 5          -32          -32
 6          -64          -64
 7         -128         -128
 8         -256         -256
 9         -512         -512
10        -1024        -1024
11        -2048        -2048
12        -4096        -4096
13        -8192        -8192
14       -16384       -16384
15       -32768       -32768
16       -65536       -65536
17      -131072      -131072
18      -262144      -262144
19      -524288      -524288
20     -1048576     -1048576
21     -2097152     -2097152
22     -4194304     -4194304
23     -8388608     -8388608
24    -16777216    -16777216
25    -33554432    -33554432
26    -67108864    -67108864
27   -134217728   -134217728
28   -268435456   -268435456
29   -536870912   -536870912
30  -1073741824  -1073741824
31  -2147483648  -2147483648
32           -1   2147483647
Program ended with exit code: 0
注意当移动位数m大于32时,移动 m%32位

右移

右移m位,右端m个位数丢失,左端不断补充符号位。最高位u右移和左移区别在于最高位符号位不会改变。

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int a=0x80000000;
    int b=0x7fffffff;
    for(int i=1;i<33;i++)
    printf("%2d %12d %12d\n",i,a>>i,b>>i);
    return 0;
}

 1  -1073741824   1073741823
 2   -536870912    536870911
 3   -268435456    268435455
 4   -134217728    134217727
 5    -67108864     67108863
 6    -33554432     33554431
 7    -16777216     16777215
 8     -8388608      8388607
 9     -4194304      4194303
10     -2097152      2097151
11     -1048576      1048575
12      -524288       524287
13      -262144       262143
14      -131072       131071
15       -65536        65535
16       -32768        32767
17       -16384        16383
18        -8192         8191
19        -4096         4095
20        -2048         2047
21        -1024         1023
22         -512          511
23         -256          255
24         -128          127
25          -64           63
26          -32           31
27          -16           15
28           -8            7
29           -4            3
30           -2            1
31           -1            0
32  -2147483648   2147483647
Program ended with exit code: 0

还有一点左移m位后溢出终值为 0,右移 溢出 负数最小终值  -1,正数终值 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值