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转换为65534printf("%u\n", num_byte2);// 输出为 65534short num_byte2_1 = -2;// 在这一步num_byte2_1还是-2printf("%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 有效小数位 6-9
字面量尾缀f或F,给不加小数点的字面常量尾缀f或F会报错
占位符:对于printf(…)来说,单精度和双精度都是 %f C99打补丁后都可以为%lf
对于scanf(…)来说,单精度只能为 %f
双精度浮点型 double ——— 8Byte
表示范围 2.3E-308 到 1.7E+308 有效小数位数 15-18
加了小数点的字面量默认为double,无需尾缀
占位符:对于printf(…)来说,单精度和双精度都是 %f C99打补丁后都可以为%lf
对于scanf(…)来说,双精度只能为 %lf
长双精度浮点型 long double ———— 32位机 10Byte; 64位机16Byte
表示范围 很大很大 有效小数位数18位以上
字面量尾缀l或L,给不加小数点的字面常量尾缀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 C89标准没有布尔类型。C99提供了_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. 和 提供的类型,略。
#include#include// 精确宽度整数类型// 64位,很多计算机底层为long long , %d 输出会数值错乱int64_t e1 = 4500000000;