两种整数:1.非负数(unsigned)2.负数、0、正数 T:补码 B:二进制 U:无符号数
1.整数数据类型:(unsigned) char、short、int、long、int32_t、int64_t….
2.无符号数的编码:假设位向量:x=[x[w-1],x[w-2],….,x[1],x[0]]
00 二进制转无符号数:B2U(x)=x[0]*2^0+x[1]*x^1+…+x[w-1]*2^(w-1)
00 很常规:U_MAX(w位)=2^(w)-1;(11…11) U_MIN=0;(00…00)
3.补码编码:最常见的有符号数的计算机表示方式。
00 二进制转有符号数:B2T(x)=-x[w-1]*2^(w-1)+x[0]*2^0+x[1]*2^1+…+x[w-2]*2^(w-2)
00 负数可看成其绝对值转为二进制后取反+1,最后再补上最高位的1
00 T_MAX(w位)=2^(w-1)-1(011…11) T_MIN(w位)=-2^(w-1)(100…00) (注意正数范围和负数范围是不对称的)
00 对于确定位数整型的打印:printf(“%” PRId32”\n”, bar); printf(“%” PRIu64”\n”, bar);….
00 有符号数的其他表示方法
0 ——1.反码:B2O(x)=-x[w-1]*(2^(w-1)-1)+x[0]*2^0+x[1]*2^1+…+x[w-2]*2^(w-2)
0 ——0 直接取反,高位补1(正数都一样,负数和补码的区别在于比补码大1)
0 ——2.原码:B2S(x)=(-1)^x[w-1]*(x[0]*2^0+x[1]*2^1+…+x[w-2]*2^(w-2))
0 ——这两种放法有一个奇怪的属性,数字0有两种不同的编码方式(100..00原)(111..11反)
4.有符号数和无符号数之间的转换(即显性转换和隐性转换)
00 处理同样字长的有符号数和无符号数之间相互转换:数值可能会变,但位不变(双方都能表示的数都是一样的)
00 T2U(x)=x+x[w-1]*2^w(即对于有符号数的正数不变,负数统一加上2^w)
00 U2T(u)=u-u[w-1]*2^w(对于〈=Tmax(2^(w-1)-1)的无符号数不变,大于的统一减去2^w)
5.C语言中的有符号数与无符号数:C未指定有符号数用哪种表示,但几乎所有的机器都用补码
00 通常一个数都是有符号的,要创建一个无符号数常量,必须加上后缀字符U(u),比如12345U
00 C允许无符号数和有符号数之间的转换,但没有精确规定方法,但大多数系统遵循的原则是底层的位保持不变
00 用printf输出时分别用%d,%u,%x以有符号十进制、无符号十进制和十六进制格式进行输出
00 当执行一个运算,如果一个运算数是有符号的,而另一个是无符号的,此时C会隐式的把有符号数转变为无符号数
00 ——(-1<0u)由于0是unsigned,所以会先把-1转变位无符号数即x^(w)-1,所以这个判断是错的
6.扩展一个数字的位表示(增大位数)
00 将一个无符号数转变为一个更大的无符号数,简单的在开头添0即可(零扩展)
00 将补码转变为一个更大的补码,则在开头添最高有效位的值(即非负数添0,负数添1)
7.截取数字(减少位数)
00 截断无符号位xmod2^k
00 截断补码数值:与无符号数一样,只是将截断后最高位转换为符号位
8.当把字看成位的集合而不是数值时,无符号位很有意义,比如每个位存放bool的,地址自然数自然是无符号的