c/c++从零玩转C语言程序设计

10-C语言进制和位运算

2018-08-30  本文已影响321人  极客江南

进制基本概念


进制转换







十进制小数转换为二进制小数

// 整数部分(除2取余)
  12
/  2
------
   6    // 余0
/  2
------
   3    // 余0
/  2
------
   1   // 余1
/  2
------
  0   // 余1
//12 --> 1100
  
// 小数部分(乘2取整数积)
  0.125
*     2
  ------
   0.25  //0
   0.25
*     2
  ------
    0.5  //0
    0.5
*     2
  ------
    1.0  //1
    0.0
// 0.125 --> 0.001

// 12.8125 --> 1100.001

二进制小数转换为十进制小数

// 整数部分(乘以2的n次方, n从0开始)
0 * 2^0 = 0
0 * 2^1 = 0
1 * 2^2 = 4
1 * 2^3 = 8
 // 1100 == 8 + 4 + 0 + 0 == 12

// 小数部分(乘以2的负n次方, n从0开始)
0 * (1/2) = 0
0 * (1/4) = 0
1 * (1/8) = 0.125
// .100 == 0 + 0 + 0.125 == 0.125

// 1100.001  --> 12.125
  0.8125
*      2
--------
   1.625  // 1
   0.625
*      2
--------
    1.25 // 1
    0.25
*      2
--------
     0.5 // 0
*      2
--------
    1.0 // 1
    0.0

// 0. 8125  --> 0.1101
1*(1/2) = 0.5
1*(1/4)=0.25
0*(1/8)=0
1*(1/16)=0.0625

//0.1101 --> 0.5 + 0.25 + 0 + 0.0625 == 0.8125

原码反码补码



位运算符

符号 名称 运算结果
& 按位与 同1为1
| 按位或 有1为1
^ 按位异或 不同为1
~ 按位取反 0变1,1变0
<< 按位左移 乘以2的n次方
>> 按位右移 除以2的n次方

9&5 = 1

 1001
&0101
------
 0001

9|5 = 13

 1001
|0101
------
 1101

9^5 = 12

 1001
^0101
------
 1100

~9 =-10
0000 0000 0000 0000 0000 1001 // 取反前
1111 1111 1111 1111 1111 0110 // 取反后

// 根据负数补码得出结果
1111 1111 1111 1111 1111 0110 // 补码
1111 1111 1111 1111 1111 0101 // 反码
1000 0000 0000 0000 0000 1010 // 源码 == -10


2<<1; //相当于 2 *= 2 // 4
  0010
<<0100

2<<2; //相当于 2 *= 2^2; // 8
  0010
<<1000
2>>1; //相当于 2 /= 2 // 1
  0010
>>0001
4>>2; //相当于 4 /= 2^2 // 1
  0100
>>0001
#include <stdio.h>
void printBinary(int num);
int main(int argc, const char * argv[]) {
    printBinary(13);
}
void printBinary(int num){
    int len = sizeof(int)*8;
    int temp;
    for (int i=0; i<len; i++) {
        temp = num; //每次都在原数的基础上进行移位运算
        temp = temp>>(31-i); //每次移动的位数
        int t = temp&1; //取出最后一位
        if(i!=0&&i%4==0)printf(" "); printf("%d",t);
    }
}

变量内存分析

  • 地址总线: 地址总线宽度决定了CPU可以访问的物理地址空间(寻址能力)
    • 例如: 地址总线的宽度是1位, 那么表示可以访问 0 和 1的内存
    • 例如: 地址总线的位数是2位, 那么表示可以访问 00、01、10、11的内存
  • 数据总线: 数据总线的位数决定CPU单次通信能交换的信息数量
    • 例如: 数据总线:的宽度是1位, 那么一次可以传输1位二进制数据
    • 例如: 地址总线的位数是2位,那么一次可以传输2位二进制数据
  • 控制总线: 用来传送各种控制信号

Qt Creator编译过程做了什么?







计算机是运算过程分析


char类型内存存储细节

字符 意义
\b 退格(BS)当前位置向后回退一个字符
\r 回车(CR),将当前位置移至本行开头
\n 换行(LF),将当前位置移至下一行开头
\t 水平制表(HT),跳到下一个 TAB 位置
\0 用于表示字符串的结束标记
\ 代表一个反斜线字符 \
\" 代表一个双引号字符"
\' 代表一个单引号字符'
    char ch1 = 'a'; 
    printf("%i\n", ch1); // 97

    char ch2 = 97;
    printf("%c\n", ch2); // a

类型说明符


short和long

#include <stdio.h>

int main()
{
    // char占1个字节, char的取值范围 -2^7~2^7
    char num = 129;
    printf("size = %i\n", sizeof(num)); // 1
    printf("num = %i\n", num); // -127
    // short int 占2个字节, short int的取值范围 -2^15~2^15-1
    short int num1 = 32769;// -32767
    printf("size = %i\n", sizeof(num1)); // 2
    printf("num1 = %hi\n", num1);

    // int占4个字节, int的取值范围 -2^31~2^31-1
    int num2 = 12345678901;
    printf("size = %i\n", sizeof(num2)); // 4
    printf("num2 = %i\n", num2);

    // long在32位占4个字节, 在64位占8个字节
    long int num3 = 12345678901;
    printf("size = %i\n", sizeof(num3)); // 4或8
    printf("num3 = %ld\n", num3);

    // long在32位占8个字节, 在64位占8个字节 -2^63~2^63-1
    long long int num4 = 12345678901;
    printf("size = %i\n", sizeof(num4)); // 8
    printf("num4 = %lld\n", num4);
    
    // 由于short/long/long long一般都是用于修饰int, 所以int可以省略
    short num5 = 123;
    printf("num5 = %lld\n", num5);
    long num6 = 123;
    printf("num6 = %lld\n", num6);
    long long num7 = 123;
    printf("num7 = %lld\n", num7);
    return 0;
}

signed和unsigned

#include <stdio.h>

int main()
{
    // 1.默认情况下所有类型都是由符号的
    int num1 = 9;
    int num2 = -9;
    int num3 = 0;
    printf("num1 = %i\n", num1);
    printf("num2 = %i\n", num2);
    printf("num3 = %i\n", num3);

    // 2.signed用于明确说明, 当前保存的数据可以是有符号的, 一般情况下很少使用
    signed int num4 = 9;
    signed int num5 = -9;
    signed int num6 = 0;
    printf("num4 = %i\n", num4);
    printf("num5 = %i\n", num5);
    printf("num6 = %i\n", num6);

    // signed也可以省略数据类型, 但是不推荐这样编写
    signed num7 = 9;
    printf("num7 = %i\n", num7);
   

    // 3.unsigned用于明确说明, 当前不能保存有符号的值, 只能保存0和正数
    // 应用场景: 保存银行存款,学生分数等不能是负数的情况
    unsigned int num8 = -9;
    unsigned int num9 = 0;
    unsigned int num10 = 9;
    // 注意: 不看怎么存只看怎么取
    printf("num8 = %u\n", num8);
    printf("num9 = %u\n", num9);
    printf("num10 = %u\n", num10);
    return 0;
}
    signed short int num1 = 666;
    signed unsigned int num2 = 666; // 报错
上一篇下一篇

猜你喜欢

热点阅读