变量和数据类型(二)

进制

二进制

二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。

  • 数据在计算机中主要以补码的形式存储。
  • 标准的C语言不支持二进制的书写,只是有的编译器进行了扩展,才支持书写二进制。
  • 区分二进制,八进制和十进制通常根据数据的前缀和后缀。二进制的前缀:0b(不区分大小写);二进制的后缀B。
//合法的二进制
int a = 0b101;  //换算成十进制为 5
int b = -0b110010;  //换算成十进制为 -50
int c = 0B100001;  //换算成十进制为 33
//非法的二进制
int m = 101010;  //无前缀 0B,相当于十进制
int n = 0B410;  //4不是有效的二进制数字

八进制

八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。一些编程语言中常常以数字0开始表明该数字是八进制。

  • 八进制的前缀:0(0不是o); 八进制的后缀:O
//合法的八进制数
int a = 015;  //换算成十进制为 13
int b = -0101;  //换算成十进制为 -65
int c = 0177777;  //换算成十进制为 65535
//非法的八进制
int m = 256;  //无前缀 0,相当于十进制
int n = 03A2;  //A不是有效的八进制数字

十六进制

十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9,A-F对应10-15。

  • 十六进制的前缀:0x或者0X(不区分大小写);十六进制的后缀:H
/合法的十六进制
int a = 0X2A;  //换算成十进制为 42
int b = -0XA0;  //换算成十进制为 -160
int c = 0xffff;  //换算成十进制为 65535
//非法的十六进制
int m = 5A;  //没有前缀 0X,是一个无效数字
int n = 0X3H;  //H不是有效的十六进制数字

进制的输出

short int long
八进制 %ho %o %lo
十进制 %hd %d %ld
十六进制 %hx 或者 %hX %x 或者 %X %lx 或者 %lX

十六进制数字的表示用到了英文字母,有大小写之分,要在格式控制符中体现出来:

  • %hx、%x 和 %lx 中的x小写,表明以小写字母的形式输出十六进制数;
  • %hX、%X 和 %lX 中的X大写,表明以大写字母的形式输出十六进制数。

八进制数字和十进制数字不区分大小写,所以格式控制符都用小写形式。如果你比较叛逆,想使用大写形式,那么行为是未定义的,请你慎重:

  • 有些编译器支持大写形式,只不过行为和小写形式一样;
  • 有些编译器不支持大写形式,可能会报错,也可能会导致奇怪的输出。

计算机内存数值存储方式

原码

一个数的原码(原始的二进制码)有如下特点:

  • 最高位做为符号位,0表示正,为1表示负。

  • 其它数值部分就是数值本身绝对值的二进制数。

  • 负数的原码是在其绝对值的基础上,最高位变为1。

下面数值以1字节的大小描述:

十进制数 原码
+15 0000 1111
-15 1000 1111
+0 0000 0000
-0 1000 0000

反码

  • 对于正数,反码与原码相同。

  • 对于负数,符号位不变,其它部分取反(1变0,0变1)。

十进制数 反码
+15 0000 1111
-15 1111 0000
+0 0000 0000
-0 1111 1111

补码

值得注意的是,原码和反码都不适合加减的运算,所以引入了补码的概念,这也是就为什么在计算机系统当中,数据大都以补码形式存储的原因。

在计算机系统中,数值一律用补码来存储。

补码特点:

  • 对于正数,原码、反码、补码相同。

  • 对于负数,其补码为它的反码加1。

  • 补码符号位不动,其他位求反,最后整个数加1,得到原码。

十进制数 补码
+15 0000 1111
-15 1111 0001
+0 0000 0000
-0 0000 0000

补码的意义

  • 统一了零的编码。

    用8位二进制数分别表示+0和-0

    十进制数 原码
    +0 0000 0000
    -0 1000 0000
    十进制数 反码
    +0 0000 0000
    -0 1111 1111

    不管以原码方式存储,还是以反码方式存储,0也有两种表示形式。为什么同样一个0有两种不同的表示方法呢?但是如果以补码方式存储,补码统一了零的编码:

    十进制数 补码
    +0 0000 0000
    -0 10000 0000由于只用8位描述,最高位1丢弃,变为0000 0000
  • 将符号位和其它位统一处理,使得利用补码的加法和减法运算不会出问题。

  • 将减法运算转变为加法运算。

  • 两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

注意

  • 赋值的时候(输入),赋值的是十进制,给的是原码。如果赋值的是八进制或者十六进制给的是补码。
  • 打印的时候(输出),十进制打印要的是原码,如果是十六进制或者八进制打印要的是数的补码。
char num = 129;//赋值的是十进制,给的是原码
printf("num = %d\n");//输出-127,十进制打印,打印的是原码

解析:

第一步:129赋值的时候是十进制,给的是原码。129的原码=反码=补码=1000 001。

第二步:但是num是有符号数类型,最高位1,计算机这是一个负数的补码(数据在计算机中存储都是以补码的形式存储)。

第三步:打印的是十进制,要的是原码,1000 0001被计算机看作是补码,负数的补码求反码得到1111 1110,负数的反码求原码得到1111 1111-->-127。

posted @ 2022-10-18 21:05  一只少年AAA  阅读(126)  评论(0编辑  收藏  举报