【C语言笔记】<八>源码补码反码及位运算

源码补码反码
int main(int argc, const char * argv[])
{
//    int占4个字节 1个字节8位
    int num = 12;
    /*
//     12的二进制
     12在内存中存储的是它的补码
     00000000  00000000 00000000 00001100
     正数的特点:(三码合一) 正数的原码就是TA的反码就是TA的补码
     
     
     -12
     二进制的最高位我们称之为符号位 
     如果符号位是0代表是一个正数,
     如果符号位是1代表是一个负数
     
     10000000  00000000 00000000 00001100 (-12的原码)
     11111111  11111111 11111111 11110011(反码, 符号位不变其它位取反)
     
     11111111  11111111 11111111 11110011
    +00000000  00000000 00000000 00000001
     _____________________________________________
     11111111  11111111 11111111 11110100(补码 , 反码+1)
     
     结论:无论正数负数在内存中存储的都是补码
     
     
     
     11111111  11111111 11111111 11110101 (补码)
    -00000000  00000000 00000000 00000001  (-1)
     _____________________________________________
     11111111  11111111 11111111 11110100 (反码)
     10000000  00000000 00000000 00001011
     
     
     */
    printf("%d\n", 0b11111111111111111111111111110101);
    return 0;
}

位运算
/*
 位运算都是针对二进制的
 &
 |
 ^
  ~
 
 
 <<
 >>
 */
int main(int argc, const char * argv[])
{

    /*
     & 按位与
     特点:只有对应的两位都是1才返回1 否则返回0
     口诀: 一假则假
     规律:任何数按位与上1结果还是那个数
     
     1001
     & 0101
     _______
     0001
     
     
      1001
     &1111
     ______
      1001
     */
    
    /*
     | 按位或
     特点:只要对应的两位其中一位是1就返回1
     口诀:一真则真
     
     1001
     | 0101
     ________
     1101
     */
    /*
     
     
     ^ 按位异或
     特点:对应的两位不相同返回1 相同返回0
     
     1001
     ^ 0101
     _______
     1100
     
     //     多个整数按位异或的结果和顺序无关
     1001
     ^ 0101
     _______
     1100
     
     1100
     ^ 0110
     _______
     1010
     
     1001
     ^ 0110
     _______
     1111
     
     1111
     ^ 0101
     _______
     1010
     
     
     //     相同整数按位异或结果是0
     1001
     ^ 1001
     _______
     0000
     
     //     任何整数按位异或上0结果不变
     1001
     ^ 0000
     _______
     1001
     
     //     任何整数按位异或上另一个整数两次结果还是那个数
     1001
     ^ 1001
     ____________
     0000
     
     0000
     ^0101
     ______
     0101
     
     */
//    int result = 9 & 5;
//    int result = 9 | 5;

//    int result = 9 ^ 5;
//     多个整数按位异或的结果和顺序无关
//    int result2 = 9 ^ 5 ^ 6;
//    int result2 = 9 ^ 6 ^ 5;
//    相同整数按位异或结果是0
//    int result3 = 9 ^ 9;
//    任何整数按位异或上0结果不变
//    int result4 = 9 ^ 0 ;
//    任何整数按位异或上另一个整数两次结果还是那个数
//    int result5 = 9 ^ 9 ^ 5;
//    int result6 = 9 ^ 5 ^ 9;
//    printf("result = %d\n", result6);
    
    /*
     ~ 按位取反
     特点: 0变1 1变0
     
     0000 0000 0000 0000 0000 0000 0000 1001
     ~1111 1111 1111 1111 1111 1111 1111 0110 (补码)
     0000 0000 0000 0000 0000 0000 0000 0001
     ______________________________________________
     1111 1111 1111 1111 1111 1111 1111 0101 (反码)
     1000 0000 0000 0000 0000 0000 0000 1010
     
     */
    
    //    int result = ~9;
    ////    printf("result = %d\n", result);
    //    printf("%d\n",0b11111111111111111111111111110110);
    return 0;
    
}
左移右移
int main(int argc, const char * argv[]) {
    
    /*
     << 左移
     
     a << n 把整数a的二进制位往左边移n位
     移出的位砍掉,低位补0, 发现左移会把原有的数值变大
     9 << 1 = 18  9 * 2(1) = 18
     9 << 2 = 36  9 * 2(2) = 26
     9 << n =  9 * 2(n)
     左移的应用场景:当要计算某个数乘以2的n次方的时候就用左移,效率最高
     
     0000 0000 0000 0000 0000 0000 0000 0000
     100 0000 0000 0000 0000 0000 0000 10010
     
     注意点:左移有可能改变数值的正负性
     */
    
    /*
     
     >> 右移
     
     a >> n 把整数a的二进制位往右边移n位
     移出的位砍掉, 缺少的以为最高位是0就补0是1就补1(是在当前操作系统下)
     9 >> 1 = 4  9 / 2(1) = 4
     9 >> 2 = 2  9 / 2(2) = 2
     右移的应用场景:当要计算某个数除以2的N次方的时候就用右移,效率最高
     0000 0000 0000 0000 0000 0000 0000 0000
     000000 0000 0000 0000 0000 0000 0000 10
     
     */
    //    int result = 9 << 2;
    int result = 9 >> 2;
    printf("result =  %d\n", result);
    return 0;
}

变量存储细节
int main(int argc, const char * argv[]) {
    // 变量为什么要有类型? 每种类型占用的内存空间不一样 int 4, char 1 double 8
    // 只要定义变量, 系统就会开辟一块存储空间给我们的变量存储数据, 内存寻址是从大到小
    // 越先定义的变量, 内存地址越大
    // 变量的地址就是所占的存储空间最小的字节地址
    
    int num;
    // 注意: 由于内存寻址是从大到小, 所以存储数据也是从大到小的存储(先存储二进制的高位, 再存储低位)
    //  高位   -->                    低位
    // 00000000 00000000 00000000 00001001
    num = 9; // 9 -->二进制 -->存储(补码)
    int value;
    value = 600; //00000000 00000000 00000010 01011000
    // %p是输出地址
    // &变量名称, 是取出变量的地址
    printf("num = %p\n", &num);
    printf("value = %p\n", &value);
    
    // 获取存储的每一位
    char *c = &value;
    for (int i = 0; i < sizeof(num); i++) {
        int result = c[i]; // 取出每个字节中存储的数据
        printf("%i\n", result);
    }
    
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容