整数数据类型
C语言中不同字长的机器和编译器会分配不同字节大小.
long类型是唯一与机器相关的.
32位机器上C语言的整数数据类型的典型取值范围
负数的取值范围比正数大1
C data type | Minimum | Maximum |
---|---|---|
char | ?128 | 127 |
unsigned char | 0 | 255 |
short [ int ] | ?32,768 | 32,767 |
unsigned short [ int ] | 0 | 65,535 |
int | ?2,147,483,648 | 2,147,483,647 |
unsigned [ int ] | 0 | 4,294,967,295 |
long [ int ] | ?2,147,483,648 | 2,147,483,647 |
unsigned long [ int ] | 0 | 4,294,967,295 |
long long [ int ] | ?9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
unsigned long long [ int ] | 0 | 18,446,744,073,709,551,615 |
64位机器上C语言的整数数据类型的典型取值范围
负数的取值范围比正数大1
C data type | Minimum | Maximum |
---|---|---|
char | ?128 | 127 |
unsigned char | 0 | 255 |
short [ int ] | ?32,768 | 32,767 |
unsigned short [ int ] | 0 | 65,535 |
int | ?2,147,483,648 | 2,147,483,647 |
unsigned [ int ] | 0 | 4,294,967,295 |
long [ int ] | ?9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
unsigned long [ int ] | 0 | 18,446,744,073,709,551,615 |
long long [ int ] | ?9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
unsigned long long [ int ] | 0 | 18,446,744,073,709,551,615 |
C语言的整数数据类型的保证的取值范围
取值范围是对称的
C data type | Minimum | Maximum |
---|---|---|
char | ?128 | 127 |
unsigned char | 0 | 255 |
short [ int ] | ?32,767 | 32,767 |
unsigned short [ int ] | 0 | 65,535 |
int | ?32,767 | 32,767 |
unsigned [ int ] | 0 | 65,535 |
long [ int ] | ?2,147,483,647 | 2,147,483,647 |
unsigned long [ int ] | 0 | 4,294,967,295 |
long long [ int ] | ?9,223,372,036,854,775,807 | 9,223,372,036,854,775,807 |
unsigned long long [ int ] | 0 | 18,446,744,073,709,551,615 |
补充:C/C++支持有符号和无符号,Java只支持有符号
无符号数的编码
用
B2Uw(x)
函数把一个位向量变成10进制数
无符号数的最大值为:
所以无符号的取值范围是
补码编码
计算机表示负数通常是补码形式
用
B2Tw(x)
把一个有符号的二进制装换成10进制
一个二进制除了符号位把剩下的位取反得到反码,再在末尾+1,得到补码
比如:1011
- 除了符号位取反:1100
- 末尾+1:1101
- 符号数决定这个数字是负数,后三位决定这个数的绝对值大小为5
- 那么这个数为-5
补码编码的取值范围为:
由于0是属于非复数的那么,表示正数的数就少了一个
机器数用补码表示的好处:
原码简单,适用于乘除运算,但用原码表示的数进行加减法运算比较复杂。
补码,减法运算可以用加法来实现,例如 [X-Y]补 = [X]补 +[-Y]补,
而且,数的符号位也可以参与运算,便于运算结果的正负及是否溢出判断。
因此在计算机中大都采用补码来进行加减及乘除运算。
(不仅是整数,小数亦可用补码表示)
确定大小的整数类型
有某个确定大小的表现编码据类型非常重要
例如
让数据类型与协议指定的数据类型兼容是非常重要的
Java要求补码表示,取值与《64位机器上C语言的整数数据类型的典型取值范围 》一样。单字节用byte,没有long long。
反码与补码
反码公式
补码公式
有符号与无符号间的转换
C语言中将short int 转换成unsight short,会改变数值而不改变位模式
比如
-12345(补码) 二进制:1100 1111 1100 0111
转换成无符号
53191(无符号) 二进制:1100 1111 1100 0111
有符号转换无符号
无符号装换有符号
总的来说对于w位的数字
- 有符号变无符号
- 正数不变
- 负数会加上2^w
- 无符号变有符号
- 如果数字小于2^(w-1),不变
- 如果数字大于2^(w-1),减2^w
运算时,运算符两边如果一个是有符号数,一个是无符号数,那么有符号数会自定转换成无符号.这种转换在逻辑运算中将显得不直观
扩展一个数字的位表示
- 将一个无符号的数转换成一个跟大范围的数据类型,只要在开头加0,这种运算叫零扩展
- 将补码数字扩展一个更大范围的数据类型,只要在前面添加最高有效位的值的副本,即最高位为0就添0为1就添1.
- 比如1010 四位的数字扩展到6位就是111010
- 对于将short类型数字变成unsigned int 时,先改变大小再从有符号变成无符号
截断数字
无符号数如果经过运算变成负数,在计算机中会被认为是一个很大的无符号数.这种特性可能成为计算机的安全隐患.为了防止这种问题,绝不使用无符号