一,数据类型的介绍
1.基本的内置类型:分为signed, unsigned(默认有符号数)
char:字符数据类型(1byte),有符号数的大小范围是-128~127,无符号数是0~255.
short:短整型(2byte),有符号数的大小范围是-2^15~2^15-1,无符号数是0~2^16-1.
int:整形(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.
long:长整形(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.
long long:更长整形(8byte),有符号数的大小范围是-2^63~2^63-1,无符号数是0~2^64-1.
float:单精度浮点数(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.
double:双精度浮点数(8byte),有符号数的大小范围是-2^63~2^63-1,无符号数是0~2^64-1.
类型的意义:类型的开辟决定了内存空间的大小,如何看待内存空间的大小
2.构造类型
数组类型,结构体类型(struct),枚举类型(enum),联合类型(union),自定义类型
3.指针类型 (int *)
空类型(void):通常同于函数的返回类型,函数的参数,指针类型
二,整形在内存中的存储(存放的是补码)
无符号数:是正数,补码就是原码;
有符号数:最高比特位为符号位,1表示负数,0表示整数;补码=(原码变成反码)+1;
在储存数据时,首先看类型(有无符号位),再看正负(最高比特位),最后储存数据;
在读取数据时,首先看类型(有无符号位),再看正负(最高比特位),最后读取数据;
三,大端小端的介绍
1,大端模式:数据低位保存在高地址中,数据的高位存在低地址中;
2,小端模式:数据的低位保存在低地址中,高位保存在高地址中;
从下面的程序判断是大端还是小端:
#include
#include
int check_sys()
{
int i = 1;
return(*(char *)&i);//(char*)&i 强转成char*类型,再解引用就是首地址(低地址);
}
int main()
{
int ret = check_sys();
if (ret == 1)
{
printf("xiaoduan\n");
}
else{
printf("daduan\n");
}
system("pause");
return 0;
}
i (0000 0001) 强制转化为char *;低位是1,首地址是低地址,则是小端。
下面是整形在内存中储存的练习:
1,输出什么
#include
int main()
{
char a=-1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
首先看char a是有符号char类型,占1byte
a=-1;a的原码为1000 0001,但是在计算机内存补码,所以需要转化为补码:反码 1111 11110,补码=反码+1为 1111 1111
再看输出的a=%d,是有符号整形,这时需要填充(填充时看变量自身的类型,无符号数填充0,有符号数看最高符号位)
填充后为1111 1111 1111 1111 1111 1111 1111 1111
输出有符号整形:补码-1变反码 1111 1111 1111 1111 1111 1111 1111 1110
1000 0000 0000 0000 0000 0000 0000 0001
则a=-1; 同理b=-1;
unsighed char c 是无符号char类型,占1byte;
c=-1,原码是1000 0001,在计算机存补码:1111 1111
输出的是c=%d,需要填充,这时变量c是无符号,则填充后为: 0000 0000 0000 0000 0000 0000 1111 1111
这时补码是个正数,原码=补码,则c=255;
2,把第一题代码不变,只改变输出,结果是什么
printf(“a=%u,b=%u,c=%u”,a,b,c);
a=%u输出的是无符号整形,也需要填充(变量a是有符号char)1111 1111 1111 1111 1111 1111 1111 1111
因为是无符号整形,则补码是正数,所以原码=补码,即输出结果为2^32-1;同理b=2^32-1;
c=%u输出的是无符号整形,需要填充(变量c是无符号)0000 0000 0000 0000 0000 0000 1111 1111,即输出c=2^8-1=255.
3,
#include
int main()
{
char a=-128;
printf("%u\n",a);
return 0;
}
char a是有符号char类型,a=-128 原码是1 1000 0000
反码是1 0111 1111
补码是1 1000 0000
由于char占1byte , 存在计算机的是1000 0000;
输出的a=%u,是无符号整形,需要填充(a变量是有符号) 1111 1111 1111 1111 1111 1111 1000 0000
输出无符号则说明补码是正数,所以原码=补码,输出a=2^31+2^30+.......+2^7=4294967168;
4,
#include
int main()
{
unsigned int i;
for(i=9;i>=0;i++)
{
printf("%u\n",i);
}
return 0;
}
unsigned int是无符号整形,即是正数(i>=0),说明for条件永成立,当i=-1时,计算机会默认为无符号数
所以这个结果是死循环。
5,
int main()
{
char a[1000];
int i;
for(i=0;i<1000;i++)
{
a[i]=-1-i;
}
printf("%d",strlen(a));
return 0;
}
当i=0时,a[0]=-1
当i=127时,a[127]=-1+(-127)=-128
-1在计算机存补码是1111 1111; -127 原码是 1111 1111,反码1000 0000,补码是1000 0001
1111 1111+1000 0001=1 1000 0000,则-1+(-127 )在计算机存1000 0000,即-128;
当i=128时,a[128]=-1+(-128)=127
-128 原码是1 1000 0000 ,反码是1 0111 1111,补码是1000 0000
1111 1111+1000 0000=1 0111 1111,则-1+(-128)在计算机存的是0111 1111,即127
当i=129时,a[129]=-1+(-129)=126
-129 的原码是1 1000 0001,反码是1 0111 1110,补码是1 0111 1111
1111 1111+1 0111 1111=10 0111 1110,则-1+(-129)在计算机存的是0111 1110,即126
像这样一直到结果为0结束。
从上面可以看出存的数有-1~-128,127~0;但是strlen不统计‘\0’,则共有255个空间。
6,
short num=32767;
short int a=num+1;
printf("%d\n",a);
32767化成二进制位0111 1111 1111 1111,加1->1000 0000 0000 0000
系统直接识别为最小值 ,不进行解码,结果为-32768.
三,浮点数在内存中的存储
1,浮点数在计算机内以二进制浮点数表示:(-1)^s*M*2^E
(-1)^s表示符号位,当s=0时,浮点数为正数,当s=1时,浮点数为负数;
M表示有效数字(小数点后面),大于等于1,小于2;
2^E表示指数位;
2,规定:对于32位的浮点数,最高的一位是符号位s,接着的八位是指数E,剩下的23位为有效数字M;
对于64位的浮点数,最高的一位是符号位s,接着的11位是指数E,剩下的52位为有效数字M;
3,下面看一个例子:
#include
#include
int main()
{
int n = 9;
float *p = (float *)&n;
printf("n的值:%d\n", n);
printf("*p的值:%f\n", *p);
system("pause");
return 0;
}
为什么把9变成浮点数就成了0.000000呢?
首先把9写成二进制0000 0000 0000 0000 0000 0000 0000 1001
它的符号位是s=0,指数部分为E=0000 0000(-127),后23位为有效数字M=000 0000 0000 0000 0000 1001
则浮点数就可以写成二进制数(-1)^0*0.000 0000 0000 0000 0000 1001*2^(-127)=1.001*2^(-127),这个浮点数是接近0的正数,所以表示成十进制小数为0.000000