1、C和C++语言中基本的数据类型有:字符型(char),×××(short, int, long), 浮点型(float, double)
同时字符型和×××还可以继续分为带符号的和不带符号的,默认情况下都是带符号的,如果想使用不带符号的,则使用时带上 unsigned说明即可,如果是带符号的,那么最高位将表示符号位,最高位为0表示为正数,最高位为1表示为负数,因此根据这个可以得到不同类型在分别带符号和不带符号的情况下表示的数据范围:
类型 | 范围 | 类型 | 范围 |
(signed)char | -128——127 | unsigned char | 0——255 |
(signed) short | -32768——32767 | unsigned short | 0——65535 |
(signed ) int | -32768——32767 | unsigned short | 0——65535 |
(signed) long | -2147483648——2147483647 | unsigend long | 0——4294967295 |
float | -3.4*10-38——3.4*1038 | double | -1.7*10-308——1.7*10308 |
2、对于字符型和×××特别需要注意其表示的范围,如果运算导致超出其范围的处理,如以下的代码:
int main() { signed char ch = 127; ch += 1; printf("%d\n", ch); return 0; }
输出结果为:-128,注意,定义ch时赋予的值为127,已经是char能表示的最大数,其最终结果-128的来历是这样的:
第一步:首先127在计算机中用二进制表示为:01111111;
第二步:01111111 + 00000001 = 10000000;
第三步:由于ch是带符号的,当最高位为1时,表示是负数,而负数的计算机中是利用补码来存储的,回忆计算负数补码的方法(首先取负数的绝对值,然后求二进制,对二进制取反,在对取反后的值加1,即为负数的补码);
第四步:于是根据求补码的反步骤,我们来求最原始的负数,由于本题中补码为10000000,首先10000000 - 00000001 = 01111111,然后对01111111取反为10000000,10000000 = 128,由于本身是负数,即ch为-128.
再看以下一段代码:
int main() { unsigned char ch = 255; ch += 1; printf("%d\n", ch); return 0; }
输出结果为:0;
其分析为:首先ch = 255提升为×××,在计算机的存储为:(000....)11111111,然后(000....)11111111+1 = (000...)0001 00000000;然后再将最后的八位二进制截取给ch,由于最后八位全是0,因此ch = 0了。
同理:对于遇到×××int short, long等出现上述情况时,我们也可以这样分析得到结果。
类型转换
1、将实型数据(包含单、双精度)赋值给整型变量时,舍弃实数的小数部分。
2、将整型数据赋值给单双精度变量时,数值不变,但以浮点数形式存储到变量中
3、将一个double型数据赋值给float数据时,截取其前面7位有效数字,存放到float变量的存储单元(32位)中。但应注意数值范围不能溢出
将一个float数据赋值给double变量时,数值不变,有效位数扩展到16位,在内存中以64位存储
4、字符型数据赋值给整型变量时,由于字符只占一个字节,而整型变量为2个字节,因此将字符数据(8位)放到整型变量的低8位中。有两种情况:
(1)如果所用系统将字符处理为无符号的量或是对unsigned char型变量赋值,则将字符的低8位放到整型变量的低8位,高8位补零。
(2)如果所用系统将字符处理为有符号的(signed char),若字符最高位为0,则整型变量高8位补零;若字符最高位为1,则高8位全补1.这称为符号扩展。
5、将一个int、short、long型数据赋值给一个char型变量时,只将其低8位原封不动地送到char型变量
将一个long型数据付给一个int型变量时,只将long型数据中的低16位原封不动地送到整型变量,这称为“截断”
6、将unsigned int型数据赋值给long int型变量时,不存在符号扩展问题,只需将高位补0即可