C语言【进制、原反补码、数据类型】

1、二进制、八进制、十进制、十六进制在C语言中的使用(赋值及输出)?

/**
	二进制 
	赋值时以 0b 或 0B 开头;
	输出时没有所属占位符, 十六进制整数输出也比较直观
*/
int num_bin = 0b110;
printf("%d\n", num_bin);	// 以十进制整数形式输出
//其他进制输出形式略,总之就是没有二进制形式的输出
/**
	八进制
	赋值时以0(零)开头;
	占位符:%o (小写字母o , 八进制整数) 
*/
int num_oct = 0123;
printf("%o\n", num_oct);	// 以八进制整数形式输出
/**
	十进制
	赋值时正常表示
	占位符:%d 表示输出形式为十进制整数
*/
int num_deci = 123456;
printf("%d\n", num_deci);
/**
	十六进制
	以0x或0X开头
	占位符: %x     输出十六进制整数(A-F输出为小写)
		   %X     输出十六进制整数(A-F输出为大写)
	       %#x    输出0x样式十六进制整数
		   %#X    输出0X样式十六进制整数
*/
int num_hex = 0xff;
printf("%x\n", num_hex);
printf("%#x\n", num_hex);
printf("%#X\n", num_hex);

拓展问题:有没有浮点类型二/八/十六进制的数的展示 ?输出呢?

似乎有,似乎用处不大。来一段:

float hex_float = 0x1P3; 
printf("hex_float = %f\n", hex_float);  // 输出为 hex_float = 8.000000

在这里,0x1P3是一种用科学计数法表示十六进制浮点数的方式。在这个例子中,1P3表示1乘以2的3次方,也就是8。

2、进制转换略。 遗留问题: 浮点数的进制转换?

3、机器数指一个数在计算机中存储的二进制原样;真值指按规则编码后表示的值,比如1001这个二进制数,如果把最高位的1表示为符号位,则其真值为-1。

4、原反补码是什么及各自的转换。

  • 原码:最高位表示符号位(0正、1负)的机器数。

  • 反码:正数反码即原码;负数反码符号位不变,其他位取反。

    反码存在的意义就是为了求补码。

  • 补码:正数的补码即原码;负数的补码即反码+1。

    补码存在的意义就是为使计算机运算更方便,因为计算机没有设计减法器,听说减法器不如用补码更简洁和高效。

    ​补码的设计原理是:让负数原码的绝对值和负数的补码相加为全零(最高位溢出),这个补全后的数即为该存储大小能表示的个数,2字节的话这个数即为65536,这样的话有效位数就全为0了。

    ​比如:2+(-2)=0。 -2的补码离有效位全0少2;+2离有效位全0多了2,对于有效位全0来说刚好互补。

    ​这样设计的好处为:作减法运算时,可视为正数和负数相加。

    ​运算时,符号位也参与运算。

    ​负数补码转原码时,也可以直接取反后+1得到。

    /**
    	下面的代码中
    		short 占两个字节,能表示65536个数,最高位溢出,有效位全0
    		-2的在内存中以补码形式存储,表示为十进制即为65534,要用%u输出
    		也可以想-2离有效位全0即65536少2,即65534
    */
    unsigned short num_byte2 = -2;
    printf("%hu\n", num_byte2);	// 输出为 65534  hu表示无符号短整型
    
    short num_byte2_1 = -2;
    printf("%hu\n", num_byte2_1);	// 输出为 65534  
    

    问题:参考上面的代码,下面的代码为什么会这样子输出?

    unsigned short num_byte2 = -2;	// 这一步将num_byte2转换为65534
    printf("%u\n", num_byte2);		// 输出为 65534
    
    short num_byte2_1 = -2;			// 在这一步num_byte2_1还是-2
    printf("%u\n", num_byte2_1);	// 输出为 4294967294  转换为无符号时short占不下了,按四个字节来,就变成了 4294967296-2, 即 4294967294
    

5、基本数据类型

  • 整型


    • 短整型 short ---------- 2Byte


      有符号短整型 signed short / short 占位符为: %hi表示范围:-32768到32767 字面量无尾缀

      无符号短整型 unsigned short占位符为: %hu表示范围:0到65535 字面量无尾缀表示


    • 整型 int ---------- 16位机 2Byte; 32位机 4Byte


      有符号整型 signed int / int 占位符: %d 表示范围: 根据位数决定

      ​一般拼写上一个没超过int范围的数默认字面量的类型为int,除非在字面量后面加尾缀。

      无符号整型 unsigned int 占位符 %u 表示范围: 根据位数决定 字面量尾缀为u或U


    • 长整型 long ----------- 32位机 4Byte; 64位机 8Byte 问题: 我64位机咋还是4Byte?  windows的问题。Linux就是8个。不同系统使用的数据模型不同,导致long表示的范围不能确定无二。


      有符号长整型 signed long / long 占位符:%ld 表示范围:不做掌握 字面量尾缀 l或L

      无符号长整型 unsigned long 占位符: %lu 表示范围:不做掌握 字面量尾缀lu或ul


    • 长长整型 long long ------------ 8Byte


      有符号长长整型 signed long long / long long 占位符: %lld 表示范围:很大很大 字面量尾缀ll或LL

      无符号长长整型 long long 占位符: %llu (l和u位置不可互换) 表示范围:很大很大 字面量尾缀llu或LLU


    注意
    任何系统的pointer(指针类型)位数和系统一致,比如64位即8Byte;       
    char、int、long long不随系统改变; 
    尽量不使用long;
    想确保int为4Byte可以使用stdint.h库里的 int32_t 类型

  • 浮点型


    • 单精度浮点型 float --------- 4Byte


      表示范围:1.2E-38 到 3.4E+38

      字面量尾缀fF,给不加小数点的字面常量尾缀f或F会报错

      占位符:对于printf(...)来说,单精度和双精度都是 %f


    • 双精度浮点型 double --------- 8Byte


      表示范围 2.3E-308 到 1.7E+308

      加了小数点的字面量默认为double,无需尾缀

      占位符:对于printf(...)来说,单精度和双精度都是 %f


    • 长双精度浮点型 long double ------------ 32位机 10Byte; 64位机16Byte


      表示范围 很大很大

      字面量尾缀lL,给不加小数点的字面常量尾缀f或F会表示为long

      占位符:%Lf


    • 浮点数打印时默认保留六位小数,可自行调整。如下:

      double num_doub = 123456789.23956;
      // 注意: 这个保留的两位是四舍五入而不是截取 (我用的gcc,别的编译器没试过)
      printf("%20.2lf\n", num_doub);		// 总共输出二十个字符,不够前面补空格。小数点后保留两位,如果整数位大于二十,则仍然完整输出整数位,小数位保留两位(注意.2后面是字母l,不是数字1)
      
      // %e 占位符可以输出浮点数的科学计数法表示形式(适用float和double) 长双用%Le(L大写)
      double num_double2 = 123.4;
      printf("%e\n", num_double2);
      

  • 字符型 char ------- 1Byte

    占位符: %c

    不能存中文字符,想存中文字符用指针或数组。

    本质就是一个整数。不同设备把char默认为有符号/无符号的类型。一般是有符号,即 -128 到 127

  • 布尔型 _Bool

6、数据类型转换

  • 隐式转换(自动类型转换)

    short(2)/ char(1) ----> int(2/4) -----> unsigned int (2/4) --------> long(4/8) ------> unsigned long(4/8) ----> long long(8) ------> float(4) ------> double(8) ------> long double(10/32)

​浮点转整型有可能出现溢出(如果整数很大)或者 精度缺失

  • 显示转换(强制类型转换,略) 整数小转大具体细节按补码计算。涉及浮点数的小转大不会。

    float num_f = 12.3f;
    double num_dou = (double) num_f;
    printf("%lf\n", num_dou);		// 输出 12.300000
    

7、sizeof(...)的使用,格式占位符,返回的类型等。

sizeof(类型/变量名/字面量/表达式)

如果不是查看 类型或表达式 的大小,可以使用 sizeof 变量名/字面量

占位符为 %zu 或 %d

返回类型为size_t,根据系统决定实际类型。

返回类型的字节个数,如果查看某个字面量的字节占用个数,查的是它默认的使用类型字节数。

8、补充

1. 转义字符

\b 退格; \n 换行符; \r 回车符; \t 制表符; \加单双引号或斜杠在特殊情况下转义为它们本身等

2. C语言中非0即为真,-1也是真。
3. <stdint.h> 和 <stdbool.h> 提供的类型,略。
#include<stdio.h>
#include<stdint.h>
// 精确宽度整数类型
// 64位,很多计算机底层为long long  , %d 输出会数值错乱
int64_t e1 = 4500000000;   
11-16 11:49