C常见基本数据类型

带符号与无符号类型 signed和unsigned
- int、stort long 都默认为带符号整型
 - signed 代表有符号,包括正数、负数和0,取值范围是-32768~32767
 - unsigned 代表无符号,只包括正数和0,取值范围是0~65535,要获得无符号类型必须指定该类型为unsigned,比如unsigned long。
 - signed、unsigned也可以修饰char,long还可以修饰double
 
unsigned char c1 = 10;signed char c2 = -10;long double d1 = 12.0;
当然不同的编译器有不同的取值范围,其实signed和unsigned的区别就是它们的最高位是否要当做符号位,并不会像short和long那样改变数据的长度,即所占的字节数
不同编译器环境下基本数据类型的存储长度(字节)
#include<stdio.h>#include<stdlib.h>int main() {printf("char \t\t size = %d\n", sizeof(char));printf("short \t\t size = %d\n", sizeof(short));printf("int \t\t size = %d\n", sizeof(int));printf("long\t\t size = %d\n", sizeof(long int));printf("long long\t size = %d\n", sizeof(long long));printf("float \t\t size = %d\n", sizeof(float));printf("double \t\t size = %d\n", sizeof(double));printf("long double\t size = %d\n", sizeof(long double));/*char size = 1short size = 2int size = 4long size = 4long long size = 8float size = 4double size = 8long double size = 8*/system("pause");return 0;}
| 类型 | 32位 | 64位 | 取值范围 | 有效保留数字 | 
|---|---|---|---|---|
| char | 1 | 1 | -128 ~ 127 | |
| void*(指针变量) | 4 | 8 | ||
| short | 2 | 2 | -32768~32767,即 -215~(215-1) | |
| unsigned short | 2 | 2 | 0~65535,即 0~(216-1) | |
| unsigned int | 4 | 4 | 0~4294967295,即 0~ (232-1) | |
| int | 4 | 4 | -2147483648 ~ 2147483647 , 即 -231~(231-1) | |
| float | 4 | 4 | 1.17549e-38 ~ 3.40282e+38 | 6~7位 | 
| double | 8 | 8 | 1.79769e+308 ~ 2.22507e-308 | 15~16位 | 
| long double | - | 16 | 1.18973e+4932 ~ 3.3621e-4932 | 18~19位 | 
| long | 4 | 8 | -9223372036854775808 ~ 9223372036854775807 | |
| unsigned long | 4 | 8 | 0 ~ 18446744073709551615 | 
- int、unsigned、long、unsigned long 、double的数量级最大都只能表示为10亿,即它们表示十进制的位数不超过10个,即可以保存所有9位整数。
 - short只是能表示5位;
 - 另外对于浮点说而言:使用double类型基本上不会有错。
 
在float类型中隐式的精度损失是不能忽视的,二双精度计算的代价相对于单精度可以忽略。
事实上,在有些机器上,double类型比float类型的计算要快得多。
float型只能保证6位有效数字,而double型至少可以保证15位有效数字(小数点后的数位),long double型提供的精度通常没有必要,而且还要承担额外的运行代价。
double是8字节共64位,其中小数位占52位,2-52=2.2204460492503130808472633361816e-16,量级为10-16,故能够保证2^-15的所有精度。
在有些机器上,用long类型进行计算所付出的运行时代价远远高于用int类型进行同样计算的代价,所以算则类型前要先了解程序的细节并且比较long类型与int类型的实际运行时性能代价。
//c++#include<iostream>#include<string>#include <limits>using namespace std;int main(){cout << "type: \t\t" << "************size**************"<< endl;cout << "bool: \t\t" << "所占字节数:" << sizeof(bool);cout << "\t最大值:" << (numeric_limits<bool>::max)();cout << "\t\t最小值:" << (numeric_limits<bool>::min)() << endl;cout << "char: \t\t" << "所占字节数:" << sizeof(char);cout << "\t最大值:" << (numeric_limits<char>::max)();cout << "\t\t最小值:" << (numeric_limits<char>::min)() << endl;cout << "signed char: \t" << "所占字节数:" << sizeof(signed char);cout << "\t最大值:" << (numeric_limits<signed char>::max)();cout << "\t\t最小值:" << (numeric_limits<signed char>::min)() << endl;cout << "unsigned char: \t" << "所占字节数:" << sizeof(unsigned char);cout << "\t最大值:" << (numeric_limits<unsigned char>::max)();cout << "\t\t最小值:" << (numeric_limits<unsigned char>::min)() << endl;cout << "wchar_t: \t" << "所占字节数:" << sizeof(wchar_t);cout << "\t最大值:" << (numeric_limits<wchar_t>::max)();cout << "\t\t最小值:" << (numeric_limits<wchar_t>::min)() << endl;cout << "short: \t\t" << "所占字节数:" << sizeof(short);cout << "\t最大值:" << (numeric_limits<short>::max)();cout << "\t\t最小值:" << (numeric_limits<short>::min)() << endl;cout << "int: \t\t" << "所占字节数:" << sizeof(int);cout << "\t最大值:" << (numeric_limits<int>::max)();cout << "\t最小值:" << (numeric_limits<int>::min)() << endl;cout << "unsigned: \t" << "所占字节数:" << sizeof(unsigned);cout << "\t最大值:" << (numeric_limits<unsigned>::max)();cout << "\t最小值:" << (numeric_limits<unsigned>::min)() << endl;cout << "long: \t\t" << "所占字节数:" << sizeof(long);cout << "\t最大值:" << (numeric_limits<long>::max)();cout << "\t最小值:" << (numeric_limits<long>::min)() << endl;cout << "unsigned long: \t" << "所占字节数:" << sizeof(unsigned long);cout << "\t最大值:" << (numeric_limits<unsigned long>::max)();cout << "\t最小值:" << (numeric_limits<unsigned long>::min)() << endl;cout << "double: \t" << "所占字节数:" << sizeof(double);cout << "\t最大值:" << (numeric_limits<double>::max)();cout << "\t最小值:" << (numeric_limits<double>::min)() << endl;cout << "long double: \t" << "所占字节数:" << sizeof(long double);cout << "\t最大值:" << (numeric_limits<long double>::max)();cout << "\t最小值:" << (numeric_limits<long double>::min)() << endl;cout << "float: \t\t" << "所占字节数:" << sizeof(float);cout << "\t最大值:" << (numeric_limits<float>::max)();cout << "\t最小值:" << (numeric_limits<float>::min)() << endl;cout << "size_t: \t" << "所占字节数:" << sizeof(size_t);cout << "\t最大值:" << (numeric_limits<size_t>::max)();cout << "\t最小值:" << (numeric_limits<size_t>::min)() << endl;cout << "string: \t" << "所占字节数:" << sizeof(string) << endl;// << "\t最大值:" << (numeric_limits<string>::max)() << "\t最小值:" << (numeric_limits<string>::min)() << endl;cout << "type: \t\t" << "************size**************"<< endl;return 0;}
macOS输出结果:
type: ************size**************bool: 所占字节数:1 最大值:1 最小值:0char: 所占字节数:1 最大值: 最小值:\200signed char: 所占字节数:1 最大值: 最小值:\200unsigned char: 所占字节数:1 最大值:\377 最小值:wchar_t: 所占字节数:4 最大值:2147483647 最小值:-2147483648short: 所占字节数:2 最大值:32767 最小值:-32768int: 所占字节数:4 最大值:2147483647 最小值:-2147483648unsigned: 所占字节数:4 最大值:4294967295 最小值:0long: 所占字节数:8 最大值:9223372036854775807 最小值:-9223372036854775808unsigned long: 所占字节数:8 最大值:18446744073709551615 最小值:0double: 所占字节数:8 最大值:1.79769e+308 最小值:2.22507e-308long double: 所占字节数:16 最大值:1.18973e+4932 最小值:3.3621e-4932float: 所占字节数:4 最大值:3.40282e+38 最小值:1.17549e-38size_t: 所占字节数:8 最大值:18446744073709551615 最小值:0string: 所占字节数:24type: ************size**************sh: pause: command not foundProgram ended with exit code: 0
数据类型转换
自动转换
自动转换发生在不同数据类型的量混合运算时,由编译系统自动完成。自动转换遵循以下规则:
- 若参与运算量的类型不同,则先转换成同一类型,然后进行运算。
 - 转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算。
 - 所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。
 - char型和short型参与运算时,必须先转换成int型。
 - 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度比左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。
 
下图表示了类型自动转换的规则:
graph TDA[char shot]-->BB[int]-->CC[unsigned]-->DD[long]-->Double
#include<stdio.h>int main(){float PI=3.14159;int s,r=5;s=r*r*PI;printf("s=%d\n",s);return 0;}
本例程序中,PI为实型;s,r为整型。在执行s=r_r_PI语句时,r和PI都转换成double型计算,结果也为double型。但由于s为整型,故赋值结果仍为整型,舍去了小数部分。
实型变量
在程序运行过程中可以改变其值的实型量被称为实型变量,实型变量分为:
- 单精度(float)
 - 双精度(double)
 - 长双精度(long double)
 
强制类型转换
强制类型转换是通过类型转换运算来实现的。其一般形式为:
(类型说明符) (表达式)
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。
例如:
(float) a; /* 把a转换为实型 */(int)(x+y); /* 把x+y的结果转换为整型 */
在使用强制转换时应注意以下问题:
- 类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
 - 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
 
#include<stdio.h>int main(void){float f=5.75;printf("(int)f=%d,f=%f\n",(int)f,f);return 0;}
本例表明,f虽强制转为int型,但只在运算中起作用,是临时的,而f本身的类型并不改变。因此,(int)f的值为 5(删去了小数)而f的值仍为5.75。
