在c语言中类型可以分为:1.内置类型(char,short,int,long,longlong,float,double);2.自定义类型
3.指针类型;4.空类型
类型的意义是:1.所创建的空间的大小;2.如何看待内存空间的视角
一.内置类型:
1.整型家族:char:(unsigned char,signed char)---因为char类型在内存中的存储的是所对应字符的ASICC码值;
short(signed short,unsigned short);
int(signed int,unsigned int);
long(unsigned long,signed long)。
2.浮点型家族:
float(单精度),double(双精度)
二.自定义类型(也称构造类型)
1.数组类型;2.结构体类型(struct);3.枚举类型(enum);4.联合类型(union)
三.指针类型(特殊的一种类型)。
四.空类型(用void 表示,应用场景有函数的返回类型,函数的参数,指针类型)。
***整型在内存中的存储***
1.首先我们要明确的一点就是整型在内存中存储的是该整数二进制的补码。(因为存储补码可以将符号位与域值位统一处理,同时,加法和减法也可以统一处理(cpu只有加法器))。
整数又有无符号位和有符号数:对于有符号数又分为正数和负数,正数的原反补相同,而负数的则不同;无符号数的原反补也相同。
在内存中数据的存储方式有:
1.大端(存储)模式:就是指数据的低位存储在内存中地址的高位,数据的高位对应存储在地址低位。
2.小段(存储)模式:就是值数据的低位存储在内存中地址的低位,数据的高位存储在内存中地址的高位。
设计一个代码判断该机器是采用大端存储还是小端存储:
#include<stdio.h>
int main{
int i=1;
char*p=&i;
if(*p==1)
{printf("小端");//0x 01 00 00 00
}
else
{
printf("大端“);}//0x 00 00 00 01
return 0;}
代码优化:
#include<stdio.h>
int check_sys()
{
int i=1;
char *p=(char*)&i;
if(*p==1)
return 1;
else
return 0;}
int main()
{
int ret=check_sys();
if(ret==1)
{
printf("小端”);
}
else{
printf("大端");
}
return 0;}
#include<stdio.h>
int main()
{
char a=-1;
//10000000 00000000 00000000 00000001
//11111111 11111111 11111111 11111110
//11111111 11111111 11111111 11111111
//先截断 11111111
signed char b=-1;//有符号数,整型提升补符号位
unsigned char c=-1;//无符号数,整型提升补0
printf("a=%d,b=%d,c=%d\n",a,b,c);//-1,-1,255
return 0;}
#include<stdio.h>
int main()
{
char a=-128;
//10000000 00000000 00000000 10000000
//11111111 11111111 11111111 01111111
//11111111 11111111 11111111 10000000
//截断--10000000
printf("%u\n",a);//整型提升补符号位,很大一个数字
//11111111 11111111 11111111 10000000
return 0;}
#include<stdio.h>
int main()
{
char a=128;
printf("%u\n",a);//-127+1=128
return 0;}
#include<stdio.h>
int main()
{
unsigned char a=200;
unsigned char b=100;
unsigned char c=0;
c=a+b;//截断
printf("%d %d\n",a+b,c);//300,44
return 0;}
#include<stdio.h>
int main()
{
unsigned int i=10;
int j=-20;
printf("%d\n",i+j);//-10 按照补码的形式进行运算,最后格式化成为有符号整数
retrn 0;}
#include<stdio.h>
int main(){
unsigned int i;
for(i=9;i>=0;i--)//无符号i永远不可能小于0,所以是个死循环
{
printf("%u\n",i);
}
}
#include<stdio.h>
int main()
{
char a[1000];
int i;
for(i=0;i<1000;i++)
{
a[i]=-1-i;}
printf("%d",strlen(a));//255
return 0;}//-1,-2,-3.....-128;-128-1=127,126,125.....0
//128+127=255
#include<stdio.h>
unsigned char i=0;
int main(){
for(i=0;i<=255;i++)
{
printf("hello world\n");}
return 0;}//死循环,无符号数char范围再0-255,当i加到255的时候加一又变成了0
************************浮点数在内存中的存储***************************
对于浮点数在内存中的存储是与整型不同的,对于32位的浮点数,最高的一位是符号位s,接着的8位是指数E,剩下的23位是有效数字M;对于64位的浮点数,最高的一位是符号位s,接着的11位是指数E,剩下的52位是有效数字M。
符号位s:当s为0则为正数,当s为1则为负数。
有效数字位M:M在存储的时候会舍去小数点前的1。M大于1小于2。
指数位E:E为一个无符号整数,意味着如果E为8位的时候,它的取值范围为0-255;E为11位的时候,它的取值范围位0-2047.。但是,在存储中E是可以是负数的,所以规定在存入内存时E的真实值要再加上一个中间数127;对于11位的E,这个中间数是1023.例如2……10的E是10,但在保存成为32位浮点数时候,必须保存为137.
9.0->1001.0->(-1)^0*1.001*2^3 :(-1)^s*M*2^E:s=0,M=1.001,E=3
在内存中为:0,10000010(130),00100000000000000000000;
0.5->0.1->(-1)^0*1.0*2^-1:s=0,M=1.0,E=-1
在内存中为:0,01010110(126),00000000000000000000000
#include<stdio.h>
int main()
{
int n=9;//00000000 00000000 00000000 00001001--补码
float*pfloat=(float*)&n;
printf("n的值为:%d\n",n);//9
printf("*pfloat的值为:%f\n",*pfloat);//0.000000 将9的补码看作浮点数存储形式输出E为00000000
//E全为0的情况
*pfloat=9.0;//1001.0->1.001*2^3->(-1)^0*1.001*2^3
//0,10000010,00100000000000000000000
printf("num的值为%d\n",n);//1091567616,将浮点存储形式看作整型补码输出
printf("*pfloat的值为%f\n",*pfloat);//9.000000
#include<stdio.h>
int main(){
float f=5.5;
//5.5->101.1->(-1)^0*1.011*2^2;s=0,M=1.011,E=2;0,129,011
//0,10000001,01100000000000000000000
//0x40b00000 放置
//(-1)^0*1,011*2^2 还原
return 0;}
指数E在内存中取出来还可分为三种起来:
1.E不全为1和0时候:指数E的计算值减去127(或者1023),得到真实值,再将有效数字M的1补上;
2.E全为0时:这时浮点数的指数E等于1-127(或者-1023)即为真实值,有效数字M不再添上第一位的1,这样是做是为了表示+-0,以及接近于0很小的数字;
3.E为全1时,这时表示无穷大的数。