C语言【C语言】6.进制,位运算,补码反码,数组等

  • 进制

    • 其次进制以0b0B开头,如0b001。(数字0休是许母O)

    • 八进制以0开头,如067。

    • 十六进制以0x0X开头,如0x48B。

    • 打印一个屡次的八进制和十六进制:

      int a = 13;
      printf("10->8: %o\n", a);
      printf("10->16: %x\n", a);
      
    • 概念一个次之前行制数、八前行制数、十六进制,打印其对应之10 进制

      int a = 0b00000000000000000000000000001101;
      printf("2->10: %d\n", a);
      
      a = 015;
      printf("8->10: %d\n", a);
      
      a = 0xd;
      printf("16->10: %d\n", a);
      
      输出结果:
      2->10: 13
      8->10: 13
      16->10: 13
      
    • 进制转换

  • 原码,反码,补码

    • 正数之原码,反码,补码都如出一辙。三码合一

    • 负数的第一各类为符号位,反码是原码取反,补码是反码加一。

    • 凑巧数和负数在微机的内存中都以补码的形式存在。

    • 于负数, 补码表示法啊是脑子无法直观看出那数值的。
      通常也要更换成为原码在算其数值。

    • 为什么要引入反码和补码?

      • 今我们清楚了微机可以起三种植编码方式表示一个数.

        对正数因为三栽编码方式的结果尚且无异, 所以不需要过多讲。

        可是对负数, 可见原码, 反码和补码是了不同之.
        既然原码才是叫人脑直接识别并用以计算表示方法, 为何
        还见面出反码和补码呢?

        首先, 因为人脑可以解第一各项是符号位,
        在测算的下我们见面因符号位,
        选择针对性真值区域的加减。但是对电脑,
        加减乘数已经是最为基础的演算, 要设计之 尽量简单.
        计算机识别”符号位”显然会受电脑的根底电路设计变得十分复杂!
        于是人们怀念生了 将符号位呢与运算的方法. 我们知道,
        根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 +
        (-1) = 0 , 所以机器可以只有加法而没减法,
        这样计算机运算的筹划虽再次简单了.

      • 例:

        计量十进制的表达式: 1-1=0

        1 – 1 = 1 + (-1) = [00000001]原 + [10000001]原 =
        [10000010]原 = -2

        若用原码表示, 让符号位吗介入计算, 显然对减法来说,
        结果是未科学的.这吗即是怎计算
        机内部不应用原码表示一个数.

        为解决原码做减法的题目, 出现了反码:

           1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原           
         = [0000 0001]反 + [1111 1110]反
         = [1111 1111]反
         = [1000 0000]原 (1111 1111,符号位不变,其他为逐位取反)
         = -0
        

        意识用反码计算减法, 结果的真值部分是是的.
        而唯一的问题其实就算应运而生于”0″这个突出的数值 上.
        虽然人们清楚上+0和-0凡是如出一辙的, 但是0带符号是从未有过其余意义的.
        而且会时有发生[0000 0000]原和 [1000 0000]原片独编码表示0。

        于是补码的出现, 解决了0的符和个别独编码的题材:

           1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原
         = [0000 0001]补 + [1111 1111]补
         = [0000 0000]补
         = [0000 0000]原
        
        • 这样0用[0000 0000]代表,
          而以前出现问题之-0虽然不在了.而且可以为此[1000
          0000]表示-128: (-1) + (-127) = [1000 0001]原 +
          [1111 1111]原 = [1111 1111]补 + [1000 0001]补 =
          [1000 0000]补
        • -1-127之结果应是-128, 在于是补码运算的结果遭遇, [1000
          0000]补 就是-128. 但是注意为实在
          上是利用以前的-0的补码来代表-128,
          所以-128连没有原码和反码表示.(对-128的补码表示[1000
          0000]补算出来的原码是[0000 0000]原本, 这是勿正确的)
  • 位运算符

    • & 按位与

      • 原理:二前进制中,与1互动&就保障原位,与0相&就为0。

      • 利用场景:

        1. 遵照个以及运算通常用来针对少数位清0或保留某些位。例如把a的要职都清0,保留低八员,那么尽管a&255。

        2. 判断奇偶: 将变量a与1召开各项与运算,若结果是1,则
          a是奇数;若结果是0,则 a是偶数。

        3. 另数和1开展&操作,得到这数之低位。

          1001

          &0001

          =0001

        4. 怀念将某某一样各置0。

          11111111

          &11111011

          =11111011

    • | 按位或

    • ^ 按位异或

      • 规律:

        1. 平整数相的结果是0。比如55=0。
        2. 基本上单整数相的结果跟顺序无关。比如567=576。因此得出结论:\_\_ab^a
          = b__。
      • 动各运算实现交换两个数之价值:

        a = a^b;
        b = b^a;
        a = a^b;
        
    • ~ 取反

  • 错误移运算符和右边移运算符

    • 管整治屡屡a的各次迈入位一体左移n位,高位丢弃,低位补0。左移n位其实就是是就以2底n次方。鉴于左移是丢弃最高位,0补最没有,所以符号位也会见吃丢掉,左移出来的结果值可能会见变动正负性。

    • 把收拾屡a的每次向前位一体下手变n位,保持符号各类非更换。右移n位其实就是是除以2的n次方。呢正数时,
      符号位为0,最高位补0。为负数时,符号位为1,最高位是补0或是补1,取决于编译系统的规定。

    • 例:

      • 描绘一个函数把一个10上制数按照次向前制格式输出

      • 分析:

        13 —–> 0000 0000 0000 0000 0000 0000 0000 1101

        0000 0000 0000 0000 0000 0000 0000 1101 13

        0000 0000 0000 0000 0000 0000 0000 0001 1

        每次取 一个往往之末梢一个二进制位

        外一个屡次和1开展&(按位与)得到其他一个频繁底二进制的终极

        一位

      • 实现:

            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);
            }
        
  • 变量的蕴藏

    • 一个变量所占据的积存空间,不仅同变量类型有关,而且还和编译器环境有关系。同一种类型的变量,在不同编译器环境下所占有的储存空间又是不一样的。

    • 外变量在内存中都是因二进制的形式储存。一个负数的二进制形式,其实就算是针对她的正数的二进制形式展开得反后还+1。

    • 变量的首地址,是变量所占存储空间字节地址最小之死去活来地方。(因为变量的字节的地点在内存中是出于良至小的,以0b00000000
      00000000 00000000
      00001010为例,00001010属低字节,位于这个变量所占4个字节的极致上面的老大字节,也不怕是地方最小的字节。类似Excel中之季个表格,低字节位于最上面(地址最小))。

  • 路说明符

    • 于64员编译器环境下:
      >

      short占2个字节(16位)

      int占4个字节(32位)

      long占8个字节(64位)

      故而,如果采取的整数不是大可怜之说话,可以运用short代替int,这样的话,更省去内存开销。

    • ANSI \ ISO制定了以下规则:
      >

      ​ short跟int至少为16位(2字节)

      ​ long至少为32位(4字节)

      ​ short的长度不可知盖int,int的长不克过long

      ​ char一定也也8个(1字节),毕竟char是咱编程能为此底极其小数据类型

      • 32号编译器:long long 占 8个字节, long 占 4个字节
      • 64各类编译器:long long 和 long 都是 8个字节
      • long long int == long long
      • long int == long
      • short int == short

  • char型数据存储原理

    • char a=‘a’ ——>
      取出’a’的ASCII码值,97,然后换2进制,存储在一个字节中。
    • 个人知道,ASCII表就是也字符设计之,因为字符在内存中储存时首先取出这字符的ASCII码值,然后换成为二进制之后存储。而且一个字符占一个字节,所以并8个,取值范围是-27~27-1,所以ASCII表也是0~127。
  • 数组

    • 初始化数组

      • int ages[3] = {4, 6, 9};
      • int nums[10] = {1,2}; // 其余的活动开化为0
      • int nums[] = {1,2,3,5,6}; //
        根据大括如泣如诉丁之因素个数确定数组元素的个数
      • int nums[5] = {[4] = 3,[1] = 2}; //
        指定元素个数,同时吃指定元素进行初始化
      • int nums[3]; nums[0] = 1; nums[1] = 2; nums[2] = 3;
        // 先定义,后初始化
      • 概念但是未初始化,数组中出价,但是是垃圾值。
      • 对数组来说,一旦闹素于初始 化,其他因素都吃与值0。
    • 测算数组中元素的个数

      • int count = sizeof(数组) / sizeof(数组[0]) // 数组的长短 =
        数组占用的总字节数 / 数组元素占用的字节数

    • 数组注意事项

      • 每当概念数组的时候[]中间只能写整型常量或者是回来整型常量的表达式。

        int ages[‘A’] = {19, 22, 33};

        printf(“ages[0] = %d\n”, ages[0]);

        int ages[5 + 5] = {19, 22, 33};

        printf(“ages[0] = %d\n”, ages[0]);

        int ages[‘A’ + 5] = {19, 22, 33};

        printf(“ages[0] = %d\n”, ages[0])

      • 荒谬写法

        • 没点名元素个数(int nums[] = {1,2,3,5,6};
          这样是可的,但是倘若先声明,并没有初始化,则是荒谬的)

          int a[]; // 错误

        • []遇莫可知扩变量

          int number = 10;

          int ages[number]; // 不报错, 但是没有初始化,
          里面是依照机值

    > int number = 10;
    > 
    > int ages[number] = {19, 22, 33} // 直接报错

  - > int ages10[5];
    > 
    > ages10 = {19, 22, 33};    // 错误。只能在定义数组的时候进行一次性(全部赋值)的初始化

  - 访问数组越界。