C [3] 运算符 - 位运算、取反、左右移

C [3] 运算符 - 位运算、取反、左右移

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <stdio.h>
 
int main()
{
    //滔Roy 2021.11.01
 
     //位运算 & | ^
    unsigned int a = 1;
    unsigned int b = 0;
    int c = 0;
    c = a & b;  //按位与运算    0&0=0; 0&1=0; 1&0=0; 1&1=1;   两位同时为“1”,结果才为“1”,否则为0
    printf("a&b 的值是 %d \n",c );   //0
    c = a | b;  //按位或运算     0|0=0; 0|1=1; 1|0=1; 1|1=1;  只要有一个为1,其值为1。
    printf("a|b 的值是 %d\n",c );   //1
    c = a ^ b;  //按位异或运算   0^0=0; 0^1=1; 1^0=1;  1^1=0;  (异值)不同为1,相同为0
    printf("a^b 的值是 %d\n",c );   //1
 
 
    //取反 `
    //int   2 或 4 字节    范围  -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
    //计算机中的有符号数有三种表示方法,即原码、反码和补码。符号位 用0表示“正”,用1表示“负”。在计算机系统中,数值一律用补码来表示和存储。 因为 使用补码,可以将符号位和数值域统一处理(包括加法和减法)
    //反码通常是用来由原码求补码或者由补码求原码的过渡码。正数的反码与其原码相同;负数的反码是对正数逐位取反,符号位保持为1.  例如:原10010=反11101  ,原11101 = 反10010 即(-2十进制)
    a =~a;
    printf("~a 的值是 %d\n",a );    //-2
    c = ~a;     //取反    即0为1 , 1为0   假设1个字节即8bit位,则1的二进制值为(原码):0000 0001  取反(补码):1111 1110  将取反的值转换成原码(1000 0010 十进制 -2):
    printf("~a 的值是 %d\n",c );   //1
 
 
    c = ~b;     //取反    即0为1 , 1为0   假设1个字节即8bit位,则0的二进制值为(原码):0000 0000  取反(补码):1111 1111  将取反的值转换成原码(1000 0001 十进制 -1):
    printf("~b 的值是 %d\n",c );    //-1
    c = ~2;     //取反            2的二进制为 010  取反 101
    printf("~2 的值是 %d\n",c );    //-3
    c = ~3;     //取反
    printf("~3 的值是 %d\n",c );   //-4
    c = ~4;     //取反
    printf("~4 的值是 %d\n",c );   //-5
    c = ~5;     //取反
    printf("~5 的值是 %d\n",c );   //-6
 
    /*
        疑问1:1取反的值为什么是 -2 ?
        1、假设:10的8位二进制
        原码:0000 1010
        反码:0000 1010   //正数的反码与原码相同
        补码:0000 1011   //反码+1
 
        2、假设:-10的8位二进制
        原码:1000 1010
        反码:1111 0101   //负数的反码是对正数逐位取反,符号位保持为1
        补码:1111 0110   //反码+1
 
        3、假设:1的8位二进制
        原码:0000 0001
        取反:1111 1110   //取反后的值,实际是“补码”值
 
        补码还原反码:1111 1101   //将补码的值 还原成原码:1、先还原成反码,即先减1 ,
        反码还原原码:1000 0010   //2、反码再还原成原码(负数的反码是对正数逐位取反,符号位保持为1)
        原码转换成10进制:-2
 
        4、假设:0的8位二进制
        原码:0000 0000
        取反:1111 1111
        补码还原反码:1111 1110  //将补码的值 还原成原码:1、先还原成反码,即先减1 ,
        反码还原原码:1000 0001(-1 十进制)
 
        5、假设:2的8位二进制
        原码:0000 0010
        取反:1111 1101
 
        补码还原反码:1111 1100  //减1
        反码还原原码:1000 0011 (-3 十进制)
 
        疑问2:为什么要用到取反? 取反有什么作用?
        目前个人的理解,取反的作用,大部分用在 开关上,即开(1),关(0),仅此而已,无需深入研究。
 
    */
 
 
    //左移 <<   左移若干位,右不足补0
    c = 1 << 2;    //1左移2位
    printf("c 的值是 %d\n",c );   //4    1的8位二进制原码:0000 0001  左移2位:0000 0100(4 十进制)
    c = 10 << 2;    //10左移2位
    printf("c 的值是 %d\n",c );   //40    10的8位二进制原码:0000 1010  左移2位:0010 1000(40 十进制)
 
    //右移 >>   右移若干位,左不足补0
    c = 1 >> 2;    //1右移2位
    printf("c 的值是 %d\n",c );   //0   1的8位二进制原码:0000 0001  右移2位:0000 0000(0 十进制)
    c = 10 >> 2;    //10右移2位
    printf("c 的值是 %d\n",c );   //2   10的8位二进制原码:0000 1010  右移2位:0000 0010(2 十进制)
 
}

  

 

 

 

创建时间:2021.11.01  更新时间:

posted on   滔Roy  阅读(358)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报

导航

点击右上角即可分享
微信分享提示