美文网首页
08 C各种进制、存储细节、位运算

08 C各种进制、存储细节、位运算

作者: 亨锅锅 | 来源:发表于2018-10-30 13:06 被阅读0次

    1、基本理解

    
    #include <stdio.h>
    
    int main()
    {
        /*
         *
         八进制  十六进制 错      十进制   错    十进制   十进制
         00011   0x001   0x7h4  10.98   0986  .089    -109
         十进制  错     二进制   十六进制  错  十进制  错      十进制
         +178   0b325  0b0010  0xffdc  96f 96.0f   96.oF  -.003
    
         在C语言中, 如果想用十六进制表示某个数, 前面需要加上0x
         在C语言中, 如果想用八进制表示某个数, 前面需要加上0
         在C语言中, 如果想用二进制表示某个数, 前面需要加上0b
         */
    
        // 注意点:
        // 1.%i %d代表以十进制输出整数
        // 2.0x和0X一样,0b和0B一样
    
    //    // 用十进制来表示
    //    int num1 = 12;
    //    printf("num1 = %i\n", num1);
    //    // 用十六进制来表示
    //    int num2 = 0xc;
    //    printf("num2 = %i\n", num2);
    //    // 用八进制来表示
    //    int num3 = 014;
    //    printf("num3 = %i\n", num3);
    //    // 用二进制来表示
    //    int num4 = 0b1100;
    //    printf("num4 = %i\n", num4);
    
    
        int num = 12;
        // 以十进制输出
        printf("%i\n", num);
        // 以八进制输出
        printf("%o\n", num);
        // 以十六进制输出
        printf("%x\n", num);
        // 以二进制输出必须自己实现(后续会讲解如何实现)
        return 0;
    }
    

    2、进制转换

    #include <stdio.h>
    
    int main()
    {
        /*
         * 进制转换
         * 十进制 --> 二进制
         * 二进制 --> 八进制
         * 二进制 --> 十六进制
         */
        /*
         * 十进制 --> 二进制
         * 规则: 除2取余, 余数倒叙
         *
         *
         * 12
         *  2
         * ---
         *  6   0
         *  2
         * ---
         *  3   0
         *  2
         * ---
         *  1   1
         *  2
         * ---
         *  0   1
         *
         * 12 --> 1100
         */
        /*
         * 15
         *  2
         * ---
         *  7  1
         *  2
         * ---
         *  3  1
         *  2
         * ---
         *  1  1
         *  2
         * ---
         *  0  1
         */
        int num = 0b1111;
        printf("%i", num);
        return 0;
    }
    

    #include <stdio.h>
    
    int main()
    {
        /*
         * 进制转换
         * 十进制 --> 二进制
         * 二进制 --> 十进制
         * 二进制 --> 八进制
         * 二进制 --> 十六进制
         */
        /*
         * 十进制 --> 二进制
         * 规则: 除2取余, 余数倒叙
         *
         *
         * 12
         *  2
         * ---
         *  6   0
         *  2
         * ---
         *  3   0
         *  2
         * ---
         *  1   1
         *  2
         * ---
         *  0   1
         *
         * 12 --> 1100
         */
        /*
         * 15
         *  2
         * ---
         *  7  1
         *  2
         * ---
         *  3  1
         *  2
         * ---
         *  1  1
         *  2
         * ---
         *  0  1
         */
    //    int num = 0b1111;
    //    printf("%i\n", num);
    
        /*
         * 二进制 --> 十进制
         * 1100 --> 十进制
         * 规则: 系数 * 基数(索引)
         * 系数: 每一位对应的值就是系数
         * 基数:
         * 例如从二进制转换到十进制, 那么二就是基数
         * 例如从八进制转换到十进制, 那么八就是基数
         * 索引:从最低位以0开始, 依次递增
         *
         * 1*2(3) + 1*2(2) + 0*2(1) + 0*2(0)
         * 1        1        0        0
         * 8      + 4      + 0      + 0
         */
    
        /*
         * 十进制转换八进制
         * 规则: 除8取余, 余数倒叙
         *
         * 24
         *  8
         * ---
         *  3  0
         *  8
         * ---
         *  0  3
         *
         * 24 --> 30
         */
    //    printf("%i\n", 030);
    
        /*
         * 十进制转换十六进制
         * 规则: 除16取余, 余数倒叙
         * 24
         * 16
         * ---
         *  1  8
         * 16
         * ---
         *  0  1
         *
         * 24 --> 18
         */
    //    printf("%i\n", 0x18);
    
        /*
         * 八进制转换十进制
         * 规则: 系数 * 基数(索引)
         * 0*8(2)  +  3 * 8(1)  +    0*8(0)
         * 0          3              0
         */
    
        /*
         * 十六进制转换十进制
         * 规则: 系数 * 基数(索引)
         *   1*16(1) + 8*16(0)
         * 0x1         8
         */
    
        /*
         * 二进制转八进制
         * 必须知道的是:
         * 1.在八进制中最大的数字 7
         * 2.三个二进制位最大能表示的数字就是7
         * 1*2(2) + 1*2(1) + 1*2(0)
         * 111
         * 所以二进制在转换为八进制的时, 把三个二进制位看做一个八进制位即可
         *   1   4
         *  001 100   --> 14
         */
        // 在C语言中不看怎么存, 只看怎么取
    //    printf("%o", 0b001100);
    
        /*
         * 二进制转十六进制
         * 必须知道的是:
         * 1.在十六进制中最大的数字 15
         * 2.四个二进制位最大能表示的数字就是15
         * 1*2(3) + 1*2(2) + 1*2(1) + 1*2(0)
         * 1111
         * 所以二进制在转换为十六进制的时, 把四个二进制位看做一个十六进制位即可
         *   3     8
         *  0011 1000   --> 0x38
         */
    //    printf("%x\n", 0b111000);
    
        /*
         * 二进制快速转换十进制
         * 64 32 16 8 4 2 1
         * 1  1  1  1 1 1 1
         */
        return 0;
    }
    

    3、存储细节

    #include <stdio.h>
    
    int main()
    {
        /*
         * 在计算机中 正整数和负整数的源码, 补码, 反码是有区别的
         */
        /*
         * 正整数的源码, 补码, 反码都是它的二进制, 三码合一
         * 12 --> 1100
         *
         * 1100 就是12的源码
         * 1100 就是12的反码
         * 1100 就是12的补码
         *
         * int类型在计算机中占用4个字节
         * 1个字节等于8位, 所以int类型总共占用32位
         *
         * 注意点: 在存储正整数的时候, 第一个(最高位)是符号位, 0代表是正数, 1代表是负数
         * 0000 0000 0000 0000 0000 0000 0000 1100
         */
    //    int num = 12;
    
        /*
         * 负整数的源码,补码,反码
         * 源码: 二进制, 将最高位变为1
         * 1000 0000 0000 0000 0000 0000 0000 1100
         * 反码: 除了符号位以外, 0变1, 1变0
         * 1111 1111 1111 1111 1111 1111 1111 0011
         * 补码: 反码+1
         * 1111 1111 1111 1111 1111 1111 1111 0011
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * ----------------------------------------
         * 1111 1111 1111 1111 1111 1111 1111 0100
         *
         * 注意点;
         * 无论是正整数还是负整数, 存储在计算机中的都是补码
         *
         *
         * 源码 -> 反码(0变1, 1变0) --> 补码(反码+1)
         * 补码 -> 反码(补码-1) -> 源码(0变1, 1变0)
         */
    //    int num = -12
        /*
         * 1 + 1
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * ----------------------------------------
         * 0000 0000 0000 0000 0000 0000 0000 0010
         */
    //    printf("%i\n", 0b00000000000000000000000000000010);
        /*
         * 1 - 1  理解为 1 + (-1)
         * 0000 0000 0000 0000 0000 0000 0000 0001 源码
         * 1000 0000 0000 0000 0000 0000 0000 0001 源码
         * ----------------------------------------
         * 1000 0000 0000 0000 0000 0000 0000 0010 错误结果
         */
    //    printf("%i\n", 0b10000000000000000000000000000010);
        /*
         * 1 - 1  理解为 1 + (-1)
         * 0000 0000 0000 0000 0000 0000 0000 0001    1补码
         *
         * 1000 0000 0000 0000 0000 0000 0000 0001    -1源码
         * 1111 1111 1111 1111 1111 1111 1111 1110    -1反码
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * ------------------------------------------
         * 1111 1111 1111 1111 1111 1111 1111 1111    -1补码
         *
         *
         * 0000 0000 0000 0000 0000 0000 0000 0001     1补码
         * 1111 1111 1111 1111 1111 1111 1111 1111    -1补码
         * -------------------------------------------
         * 0000 0000 0000 0000 0000 0000 0000 0000    0
         */
    
    
        /*
         * 4 - 6 --> 4 + (-6)
         * 0000 0000 0000 0000 0000 0000 0000 0100  4补码
         *
         * 1000 0000 0000 0000 0000 0000 0000 0110  -6源码
         * 1111 1111 1111 1111 1111 1111 1111 1001  -6反码
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * -------------------------------------------
         * 1111 1111 1111 1111 1111 1111 1111 1010  -6补码
         *
         *
         *
         * 0000 0000 0000 0000 0000 0000 0000 0100  4补码
         * 1111 1111 1111 1111 1111 1111 1111 1010  -6补码
         * 1111 1111 1111 1111 1111 1111 1111 1110  补码的结果
         *
         * 注意点: 当前计算出来的是正确结果的补码, 要想知道正确结果是多少, 需要将补码转换为源码
         *
         * 1111 1111 1111 1111 1111 1111 1111 1110  结果的补码
         * 0000 0000 0000 0000 0000 0000 0000 0001
         * -------------------------------------------
         * 1111 1111 1111 1111 1111 1111 1111 1101  结果的反码
         * 1000 0000 0000 0000 0000 0000 0000 0010  结果的源码  -2
         */
    
        /*
         0101
       + 0001
         -----
         0102 --> 0110
    
         0110 --> 0102
       - 0001     0001
        ---------------
                  0101
       */
    
        return 0;
    }
    

    4、位运算

    
    #include <stdio.h>
    
    int main()
    {
        /*
         * & 按位与
         * | 按位或
         * ~ 按位取反
         * ^ 按位异或
         */
    
        /*
         * & 按位与
         * 规则: 一假则假
         * 在C语言中0代表假, 1代表真
         * 9 & 3 = ?
         *
         *   0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
         * & 0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
         * -----------------------------------------------
         *   0000 0000 0000 0000 0000 0000 0000 0001 // 1
         *
         * 12 & 8
         *  0000 0000 0000 0000 0000 0000 0000 1100
         *& 0000 0000 0000 0000 0000 0000 0000 1000
         * -----------------------------------------------
         *  0000 0000 0000 0000 0000 0000 0000 1000
         */
    //    printf("%i\n", 9 & 3);
    //    printf("%i\n", 12 & 8);
    
        /*
         * | 按位或
         * 规则: 一真则真
         * 9 | 3 = ?
         *  0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
         *| 0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
         *  -----------------------------------------------
         *  0000 0000 0000 0000 0000 0000 0000 1011
         */
    //    printf("%i\n", 9 | 3);
    
        /*
         * ~ 按位取反
         * 规则: 真变假, 假变真
         * ~9 = ?
         * 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
         *~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 // 结果的源码 -10
         */
    //    printf("%i\n", ~9);
    
        /*
         * ^ 按位异或
         * 规则: 相同为0, 不同为1
         * 9 ^ 3 = ?
         * 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
         *^0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
         *-------------------------------------------
         * 0000 0000 0000 0000 0000 0000 0000 1010 // 10
         */
        printf("%i\n", 9 ^ 3);
        return 0;
    }
    

    #include <stdio.h>
    
    int main()
    {
    
        /*
         * & 按位与
         * 规则: 一假则假
         * 规律: 任何一位和1相与, 结果还是原来的那一位
         * 0000 0000 0000 0000 0000 0000 0000 0001 // 1的补码
         *&0000 0000 0000 0000 0000 0000 0000 0001
         * -----------------------------------------
         * 0000 0000 0000 0000 0000 0000 0000 0001
         *
         * 0000 0000 0000 0000 0000 0000 0000 0000 // 0的补码
         *&0000 0000 0000 0000 0000 0000 0000 0001
         * -----------------------------------------
         * 0000 0000 0000 0000 0000 0000 0000 0000
         *
         * 0000 0000 0000 0000 0000 1011 0000 0000 // 0的补码
         *&0000 0000 0000 0000 0000 1111 0000 0000
         * -----------------------------------------
         * 0000 0000 0000 0000 0000 1011 0000 0000
         *
         */
    //    int res1 = 1 & 1;
    //    printf("%i\n", res1);
    //    int res2 = 0 & 1;
    //    printf("%i\n", res2);
    
        /*
         *
         * ^ 按位异或
         * 规则: 相同为0, 不同为1
         * 规律:
         * 1.任何两个相同的值异或之后的结果都是0
         * 2.任何一个数和0异或之后的结果还是那个数
         * 3.任何一个数异或另外一个数两次之后, 结果还是那个数
         */
    //    int res1 = 5 ^ 5;
    //    printf("%i\n", res1);
    //    int res2 = 9 ^ 9;
    //    printf("%i\n", res2);
    
    //    int res1 = 5 ^ 0;
    //    printf("%i\n", res1);
    //    int res2 = 9 ^ 0;
    //    printf("%i\n", res2);
    
    //    int res1 = 18 ^ 5 ^ 5;
    //    printf("%i\n", res1);
    //    int res2 = 22 ^ 9 ^ 9;
    //    printf("%i\n", res2);
    
        // 应用场景: 简单的加密
        int pwd = 123456789;
        int res = pwd ^ 998;
        printf("加密之前: %i\n", pwd);
        printf("加密之后: %i\n", res);
        int res2 = res ^ 998;
        printf("解密之后: %i\n", res2);
        return 0;
    }
    

    install B小案例

    
    #include <stdio.h>
    void test1();
    void test2();
    int main()
    {
        /*
         * 需求: 要求判断用户输入的数据是奇数还是偶数
         */
        /*
    //    int num = 7;
    //    if(0 == (num % 2)){
    //        printf("%i是偶数\n", num);
    //    }else{
    //        printf("%i是奇数\n", num);
    //    }
        */
    
        /*
        int num = 12;
        // 注意点: 三目是一个运算符, 所以必须有结果
        // 也就是 结果A和结果B的位置放的必须是变量,常量, 表达式
        // 如果放的是一个函数, 那么这个函数必须有返回值
    //    0 == (num % 2) ? printf("%i是偶数\n", num) : printf("%i是奇数\n", num);
    //    0 == (num % 2) ? test1() : test2();
    
        // printf函数的返回值, 是我们打印了多少个字符
    //    int res = printf("李"); // 如果放的是中文, 是2还是3不确定, 根据当前的编码方式GBK UTF-8
    //    printf("res = %i\n", res);
         */
    
    
        /*
         * 8 偶数
         *   1000
         * & 0001
         * -------
         *   0000  --> 0
         *
         * 12 偶数
         *   1100
         * & 0001
         * -------
         *   0000  --> 0
         *
         *
         * 9 奇数
         *   1001
         * & 0001
         * -------
         *   0001  --> 1
         *
         * 13 奇数
         *   1101
         * & 0001
         * -------
         *   0001  --> 1
         */
    
        int num = 4;
    //    if(1 == (num & 1)){
    //        printf("%i是奇数\n", num);
    //    }else{
    //        printf("%i是偶数\n", num);
    //    }
    
        if(num & 1){
            printf("%i是奇数\n", num);
        }else{
            printf("%i是偶数\n", num);
        }
    
        return 0;
    }
    void test1(){
        printf("test1\n");
    }
    void test2(){
        printf("test2\n");
    }
    

    #include <stdio.h>
    
    int main()
    {
        /*
         * << 左移
         * >> 右移
         */
        /*
          9 << 1
          0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
          000 0000 0000 0000 0000 0000 0000 10010 // 9的补码
    
          9 << 2
          0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
          00 0000 0000 0000 0000 0000 0000 100100// 9的补码
    
          移动规则: 从符号位开始整体移动, 多余的砍掉, 缺少的用零补
          计算规律: 一个数左移几位就是 这个数乘以2的多少次幂
          9 * 2(1) = 18
          9 * 2(2) = 36
          应用场景: 在企业开发中一旦想要某个数乘以2的多少次幂, 就要想到左移
         */
    //    printf("%i\n", 9 << 1);
    //    printf("%i\n", 9 << 2);
    
        /*
         0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
         00000 0000 0000 0000 0000 0000 0010 010
    
    
         0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
         000000 0000 0000 0000 0000 0000 0010 01
    
    
         移动规则: 除符号位以外整体右移, 多出来的砍掉, 缺少的用符号位填充
         计算规则: 一个数右移几位就是 这个数除以2的多少次幂
    
         36 / 2(1) = 18
         36 / 2(2) = 9
         应用场景: 在企业开发中一旦想要某个数除以2的多少次幂, 就要想到右移
         */
    //    printf("%i\n", 36 >> 1);
    //    printf("%i\n", 36 >> 2);
    
        /*
         0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
         00000 0000 0000 0000 0000 0000 0000 100  --> 4
         */
        printf("%i\n", 9 >> 1);
        /*
         * 1000 0000 0000 0000 0000 0000 0000 1001 // -9源码
         * 1111 1111 1111 1111 1111 1111 1111 0110 // -9反码
         * 1111 1111 1111 1111 1111 1111 1111 0111 // -9补码
         *
         0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
         11111 1111 1111 1111 1111 1111 1111 011 // 右移完毕的结果, 补码
         0000 0000 0000 0000 0000 0000 0000 0001
         11111 1111 1111 1111 1111 1111 1111 010 // 右移完毕的结果, 反码
         10000 0000 0000 0000 0000 0000 0000 101 // 右移完毕的结果, 源码
         */
        printf("%i\n", -9 >> 1);
    //    printf("%i\n", -9 / 2);
    
    
        return 0;
    }
    

    #include <stdio.h>
    
    int main()
    {
        /*
         * 要求将用户输入的整数, 以二进制的形式输出
         * 0000 0000 0000 0000 0000 0000 0000 1001
         * 0000 0000 0000 0000 0000 0000 0000 0001
         */
    
        int num = 9;
    //    int temp = (num >> 3) & 1;
    //    printf("temp = %i\n", temp);
    //    temp = (num >> 2) & 1;
    //    printf("temp = %i\n", temp);
    //    temp = (num >> 1) & 1;
    //    printf("temp = %i\n", temp);
    //    temp = (num >> 0) & 1;
    //    printf("temp = %i\n", temp);
    
    //    for(int i = 0; i < 32; i++){
    //        int temp = (num >> 31 - i) & 1;
    //        printf("%i", temp);
    //    }
    
        char ch = 'a';
    //    printBinary(num);
          printBinary(ch);
          printf("%i\n", 0b01100001);
    
        return 0;
    }
    void printBinary(char value){
        // int 4 --> 32
        // char 1 --> 8
        // 在企业开发中 , 数字我们称之为魔鬼
        int len = sizeof(value) * 8;
        for(int i = 0; i < len; i++){
            int temp = (value >> (len - 1 - i)) & 1;
            printf("%i", temp);
            if(((i+ 1) % 4) == 0){
                printf(" ");
            }
        }
        printf("\n");
    }
    

    #include <stdio.h>
    
    int main()
    {
        /*
         * 需求: 交换两个变量的值
         *
         * int a = 10; int b = 20;
         */
    
        int a = 10;
        int b = 20;
        printf("交换之前a = %i, b = %i\n", a, b);
    //    int temp = a;
    //    a = b;
    //    b = temp;
    //    printf("交换之后a = %i, b = %i\n", a, b);
    
    //    a = a + b; // a = 10 + 20; a = 30;
    //    b = a - b; // b = 30 - 20; b = 10;
    //    a = a - b; // a = 30 - 10; a = 20;
    //    printf("交换之后a = %i, b = %i\n", a, b);
    
    //    a = a ^ b;
    //    b = a ^ b; // b = a ^ (b ^ b);  b = 10;
    //    a = a ^ b; // a = (a ^ a) ^ b ; a = 20;
    
         b = a ^ b;
         a = a ^ b; // a = a ^ a ^ b; a = b;  a = 20;
         b = a ^ b; // b = a ^ b ^ b; b = a;  a = 10;
        printf("交换之后a = %i, b = %i\n", a, b);
        return 0;
    }
    

    #include <stdio.h>
    
    int main()
    {
        /*
         * 变量的内存分析
         * 1.内存是连续的
         * 2.内存地址从打到小
         * 3.计算机会从内存地址大的开始分配内存(内存寻址从大到小)
         * 也就是说先定义的变量内存地址大于后定义的变量
         *
         */
        /*
         * 0000 0000 0000 0000 0000 0000 0000 1001 // 补码
         *
         * 规则: 由于内存寻址是从大到小, 所以存储补码也是从大到小(也就是从高位开始存储)
         */
        int num1 = 9;
        int num2 = 7;
        printf("num1 %p\n", &num1);
        printf("num2 %p\n", &num2);
    
        char *ch = &num1;
        for(int i = 0; i < 4; i++){
            printf("%i\n", ch[i]);
        }
        printf("%p\n", ch++);
        printf("%p\n", ch++);
        printf("%p\n", ch++);
        printf("%p\n", ch++);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:08 C各种进制、存储细节、位运算

          本文链接:https://www.haomeiwen.com/subject/eszgnftx.html