zoukankan      html  css  js  c++  java
  • c11---位运算相关

    //
    //  main.c
    //  03-原码反码补码
    
    #include <stdio.h>
    
    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
    ", 0b11111111111111111111111111110101);
        return 0;
    }
    //
    //  main.c
    //  01-进制
    #include <stdio.h>
    
    int main(int argc, const char * argv[])
    {
    //     1.默认就是10进制
        int num = 12;
    //    2.在前面加上一个0就代表八进制
        int num1 = 014;
        
    //    %d是以十进制的方式输出一个整数
        printf("%d
    ", num1);
    //    %o是以八进制的方式输出一个整数
        printf("%o
    ", num);
        
    //    在数值前面加上0b就代表二进制
        int num2 = 0b1100;
        printf("%d
    ", num2);
    //    在数值前面加上0x就代表十六进制
        int num3 = 0xc;
        printf("%d
    ", num3);
    //     %x是以十六进制的方式输出一个整数
        printf("%x
    ", num);
        
    //     口诀:不看你怎么存,只看你怎去取
        
        return 0;
    }
    //
    //  main.c
    //  02-进制转换
    
    #include <stdio.h>
    
    int main(int argc, const char * argv[])
    {
    
        /*
         十进制  -> 二进制
         9
         转换原理:除2取余 倒序读取
         
         
         9/2  4  1
         4/2  2  0
         2/2  1  0
         1/2  0  1
         
         9 --> 1001
         
         
         二进制 --> 十进制
         1001
         转换原理:乘以2的幂数(幂数从0开始), 然后相加
         
         1 * 2(0) = 1
         0 * 2(1) = 0
         0 * 2(2) = 0
         1 * 2(3) = 8
         
         1 + 0 + 0 + 8 = 9
         
        1 1 1  1 1
       16 8 4  2 1
    
         
         N位二进制的取值范围
         1位  取值范围 0~1  0~2的1次方-1
         2位  取值范围 0~3  0~2的2次方-1
         3位  取值范围 0~7  0~2的3次方-1
         n位  取值范围  0~2(n)-1
         
         000
         001
         010
         011
         100
         101
         110
         111
         
         
         11111 0~ (32-1)
         
         
         二进制转换为八进制  进制越大表示的位数就越短
         规律:三个二进制位代表一个八进制位  
         因为3位的最大取值是7 而八进制是逢八进一
         
         1个字节 8位
         000   0
         001   1
         100   4
         
         014
    
         
         二进制转换为十六进制
         规律:四个二进制位代表一个十六进制位
         因为4位的最大取值是15, 而十六进制是逢十六进一
         
         0000 0
         1100 c
         
         0xc
         
         */
        printf("%d
    ", 0b1001);
        
        return 0;
    }
    //
    //  main.c
    //  05-位运算
    
    #include <stdio.h>
    /*
     位运算都是针对二进制的
     &
     |
     ^
      ~
     
     
     <<
     >>
     */
    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
    ", 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
    ", result);
        //    printf("%d
    ",0b11111111111111111111111111110110);
        return 0;
        
    }
    //
    //  main.c
    //  位运算符2
    //
    //  Created by xiaomage on 15/6/9.
    //  Copyright (c) 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    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
    ", result);
        return 0;
    }
    //
    //  main.c
    //  位运算符练习1
    //
    //  Created by xiaomage on 15/6/9.
    //  Copyright (c) 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    void printBinay(int value);
    
    int main(int argc, const char * argv[]) {
        /*
         要求定义一个函数, 传入一个整数, 输出该整数的二进制
         %i %o %x
         
         0000 0000 0000 0000 0000 0000 0000 1001
        &0000 0000 0000 0000 0000 0000 0000 0001
         
         // 1.让9的二进制向右移31, 就可以获取到9得最高位的二进制, 然后让9的二进制的最高位和1相&, 那么就可以获得9的最高位
         // 2.让9的二进制向右移30, 就可以获得9二进制的第二位
         // 3.以此类推, 直到0位置
         
         技巧:
         1.任何数与1相&都是那个数
         2.利用位移取出每一位
         */
        int num = 15;
        printBinay(num);
        return 0;
    }
    void printBinay(int value)
    {
        // 1.定义变量需要向右移动的位数
        int offset = 31;
        // 2.通过循环取出每一位
        while (offset >=0) {
            int result  = (value >> offset) & 1;
            printf("%i", result);
            // 3.每次取出一位就让控制右移的变量-1
            offset--;
            if ((offset+1) % 4 == 0) {
                printf(" ");
            }
        }
        printf("
    ");
    }
    //
    //  main.c
    //  位运算符练习2
    
    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        // 利用位运算符, 判断一个数的奇偶性
        int num = 9;
        
        // 开发中常用的方式
        if (num % 2 == 0) {
            printf("偶数
    ");
        }else
        {
            printf("奇数
    ");
        }
        
        // 注意: 三目(三元)运算符, 的结果A和结果B如果是表达式, 那么必须有返回值
        (num % 2 == 0) ? printf("偶数
    "):printf("奇数
    ");
        
        int length = printf("");
        printf("------%i
    ", length);
        
        
        /*
         1001 9
         1011 11
         
         1010 10
         1100 12
         通过观察, 我们发现如果是偶数, 那么二进制的最后一位是0, 如果是奇数那么二进制的最后一位是1
         */
        /*
        if ((num & 1) == 1)
        {
            printf("奇数
    ");
        }else
        {
            printf("偶数
    ");
        }
         */
        
        if ((num & 1))
        {
            printf("奇数
    ");
        }else
        {
            printf("偶数
    ");
        }
        return 0;
    }
    //
    //  main.c
    //  变量的存储细节
    //
    //  Created by xiaomage on 15/6/9.
    //  Copyright (c) 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    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
    ", &num);
        printf("value = %p
    ", &value);
        
        // 获取存储的每一位
        char *c = &value;
        for (int i = 0; i < sizeof(num); i++) {
            int result = c[i]; // 取出每个字节中存储的数据
            printf("%i
    ", result);
        }
        
        return 0;
    }
    //
    //  main.c
    //  char基本概念
    //
    //  Created by xiaomage on 15/6/9.
    //  Copyright (c) 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        
        
        // 研究的问题: char类型的变量在内存中是如何存储的?
        // char 1个字节
        int num;
        char charValue;
        charValue = 'a'; // 计算机智能识别0和1
        // a == 97 == 01100001
        int size = sizeof(charValue);
        printf("%i
    ", size);
        printf("num = %p
    ", &num);
        printf("char = %p
    ", &charValue);
        
        // 在C语言中, 不看怎么存, 只看怎么取
        printf("%c
    ", charValue);
        printf("%i
    ", charValue);
        
         字符6和数字6就是完全不相同的两个数
        char c1 = 6; // 00000110
        char c2 = '6';// 00110110
        
        printf("%i
    ", c1);
        printf("%i
    ", c2);
        
        
        // char类型在某些情况下可以当做整型来用
        // 如果对内存要求特别严格, 而且需要存储的整数不超过char类型的取值范围, 那么就可以使用char类型来代替int类型
        // -2(7)~2(7)-1   == -128 ~ 127
        char c = 129; // 1000 0000
        printf("%i
    ", c);
        
        return 0;
    }
    //
    //  main.c
    //  类型说明符
    
    #include <stdio.h>
    /*
     类型说明符:
     1.说明长度的(它可以用于修改类型所占用的存储空间的大小)
     short; short == short int  == 2个字节 == %hi/ %hd
     long; long == long int  == 8个字节 == %li / %ld
     long long; == long long int  == 8个字节 == %lli / %lld
     
     用于说明数据类型, 一般情况下和int配合使用
     
     2.说明符号位(它可以用于修改符号位是否用于正负数)
     unsigned; 无符号 , 取值正数和零 == %u
     signed; 有符号, 默认就是有符号 , 取值 正数和零以及负数
     
     3.不同类型的说明符可以混合使用
     unsigned short
     signed long
     // 注意: 相同类型不能在一起使用
     unsigned signed
     */
    int main(int argc, const char * argv[]) {
        
        // int  == 4个字节 == -2(31)~2(31)-1
        
        int num = 12345678901;
        printf("num = %i
    ", num);
        
        
        // int == 4个字节, long int == 8个字节 == -2(63)~2(63)-1
        long int num1 = 12345678901;
        printf("num1 = %li
    ", num1);
        
        // long int == long
        // 用%li 或者 %ld来输出long类型的数据
        // C语言中不看怎么存, 只看怎么取
        long num2 = 12345678901;
        printf("num2 = %li
    ", num2);
        
        // long long
        // 在64位变一下, 基本没区别, 但是如果是在32位就有区别
        // 32位下long占4个字节, long long 占8个字节
        // 注意: 如果使用long long修饰变量, 那么输出的时候需要使用%lli或者%lld
        long long int num3 = 12345678901;
        printf("num3 = %lli
    ", num3);
        
        printf("long long  = %i, long  = %i
    ", sizeof(num3), sizeof(num2));
        
        // long long int == long long
        long long num4 = 12345678901;
        printf("num4 = %lli
    ", num4);
        
        
        
        // int == 4个字节 == -2(31)~2(31)-1
        int num = 9; // 0000 1001
        printf("num = %i
    ", num);
        
        // 如果以后需要保存的数据的取值范围没有超过short int的取值范围, 可以使用short int来保存
        // 但是在企业级开发中很少使用
        // short int == 2个字节 == -2(15)~2(15)-1
        short int num1 = 9;
        printf("num1 = %i
    ", num1);
        
        // short int == short
        // 如果要输出short int类型的数据, 可以使用%hi或者%hd
        short num2 = 9;
        printf("num2 = %hi
    ", num2);
        
        printf("short = %i, int = %i
    ", sizeof(num1), sizeof(num));
        
        
        // signed 有符号
        // 如果给变量加上修饰符signed, 代表当前变量的取值可以是正数 / 负数/ 零
        // 如果给变量加上修饰符signed, 就代表把二进制的最高位作为符号位
        // 而且默认情况下所有变量都是有符号的(signed)
        signed int num = 0;  // 正数 / 负数/ 零 int == -2(31)~2(31)-1
        printf("num = %i
    ", num);
        
        // unsigned 代表无符号. 无符号就代表当前变量的取值只能是正数 / 零
        // 如果给变量加上修饰符unsigned, 就代表"不"把二进制的最高位作为符号位
    
        // 如果想打印无符号的变量, 只能用%u
        unsigned int num1 = -12;
        printf("num1 = %u", num1);
        
        
        // 不同类型的说明符可以混合使用
        unsigned long int num = 99;
        printf("num = %lu
    ", num);
        
        signed short int num1 = 23;
        printf("num1 = %hi
    ", num1);
        
        // 注意: 相同类型的说明符不能同时在一起使用
    //    short long int num2 = 998;
    //    unsigned signed  int num3 = 998;
        
        return 0;
    }
  • 相关阅读:
    容器
    最大公共子串
    HTTPS复习
    进程同步算法
    Android系统机制
    【springBoot】之快速构建一个web项目
    【springBoot】之概述
    【java】之深入理解JVM
    【java】之equals和==区别
    【AMQ】之JMS Mesage structure(JMS消息结构)
  • 原文地址:https://www.cnblogs.com/yaowen/p/7383208.html
Copyright © 2011-2022 走看看