目录
数据类型介绍
字符 | 类型 | 字节 |
char | 字符型(整型) | 1 |
int | 整型 | 4 |
short | 短整型 | 2 |
long | 长整型 | 4/8 |
long long | 更长的整型 | 8 |
float | 单精度浮点数 | 4 |
double | 双精度浮点数 | 8 |
数据类型的意义:
1.使用这个类型开辟内存空间的大小(大小决定了使用范围)
2.如何看待内存空间的视角
数据类型的基本归类
整型家族
char signed char unsigned char
int signed int unsigned int
short signed short unsigned short
long signed long unsigned long
浮点数家族
float
double
构造类型
数组类型:int arr[10]->int [10](类型)
结构体类型:struct
枚举类型:enum
联合类型:union
指针类型
int *p
char *p
float *p
结构体指针
空类型
void 表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型
小结
signed unsigned 表示有无符号的区别
signed 最高位为符号位
unsigned 最高位为数值位
字符是用ASCII码值存储的,所以char属于整型
整型在内存中的存储
一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型所决定的
下面我们来了解以下两个数据是如何在内存中存储的
int a=10
int b=-10
原码,反码,补码
整型的二进制表达方式有三种:原码,反码,补码
三种表达方式均有符号位和数值位两部分:
符号位正数为0,负数为1
数值位
正数:原码,反码,补码都相同
负数:原码
反码=原码符号位不变,其他位按位取反
补码=反码+1
对于整型来说,在计算机中存储的实际上是补码
接下来让我们看上文提到的两个数据int a=10,int b=-10是如何存储的(这里计算机表示的是十六进制,实际在计算机中存储的是二进制)
a变量:
原码:00000000 00000000 00000000 00001010
反码:00000000 00000000 00000000 00001010
补码:00000000 00000000 00000000 00001010
b变量
原码:100000000 00000000 00000000 00001010
反码:1111111111 111111111 111111111 111110101
补码:1111111111 111111111 111111111 111110110
大小端介绍
这里我们发现数据是倒着存储的
数据的存储方式有两种,大端存储和小端存储
大端存储:将数据的低位存储在内存的高地址中,而数据的高位存储在内存的低地址中
小端存储:将数据的高位存储在内存的低地址中,而数据的低位存储在内存的高地址中
百度面试题
设计一个小程序来判断当前机器的字节序
练习题
1.输出什么?
#include <stdio.h>
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;
}
a=-1 b=-1 c=255
2.输出什么?
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
a=4294967168
3.
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
a=4294967168
4.
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
i+j=-3
5.
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
死循环
6.
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
255
7.
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
死循环
浮点型在内存中的存储
例子
#include <stdio.h>
int main()
{
int n = 9;
float* pfloat = (float*)&n;
printf("n的值,%d\n", n);
printf("*pfloat的值为:%f\n", n);
*pfloat = 9.0;
printf("n的值为:%d\n",n);
printf("*pfloat的值为:%f\n", *pfloat);
return 0;
}
浮点数的储存规则
任意一个二进制浮点数都可以表示为
(-1)^S * M * 2^E
S:用来表示正负,s为1,(-1)^S为负,S为0,(-1)^S为正
E:2^E表示指数位
M:M表示有效数字,0<M<1
举例:
5.5
转化为二进制为101.1===》1.011*2^2
S: 0 E:2 M:1.011
单精度浮点数:
最高位为符号位S,接下来8位为指数位E,剩下的23位为有效数字M
双精度浮点数
最高位为符号位S,接下来11位为指数位E,剩下的52位为有效数字M
M,E
M:
1<=M<2,在计算机保存时默认这个值为1,所以可以省略,以32位浮点数举例,留给M的只有23位,当第一位省略后,可以保存24位
E:
首先E为一个无符号的正数,但是从科学计数法中我们可以看出E是可以为负数的,所以这个时候我们需要引入一个中间数,对于8位的E,这个数是127,对于11位的E,这个数为1023,在内存中存储的E是原本指数与中间数相加之后的结果
E的取出可以分为三种情况
1.E不全为0或E不全为1
E的计算值减去127(1023),再将M的值加上前面的1
2.E全为0
E为1-127(1023)
M不再加上前面的1,而是表示为0.xxxxxxxx的形式,以表示为+(-)0,以及接近0的很小的数字
3.E全为1
这时有效数字M全为0,表示+(-)无穷大
分析例题
#include <stdio.h>
int main()
{
int n = 9;
float* pfloat = (float*)&n;
printf("n的值,%d\n", n);
printf("*pfloat的值为:%f\n", n);
*pfloat = 9.0;
printf("n的值为:%d\n",n);
printf("*pfloat的值为:%f\n", *pfloat);
return 0;
}
这个我们可以分为2部分
第一部分
n的值为9
n的二进制表示为
00000000 00000000 00000000 00001001
当他强制转化为浮点数
0 00000000 00000000000000000001001
S:0 E:1-127 M:0.00000000000000000001001
v=(-1)^0 * 0.00000000000000000001001 * 2^(-126)=1.001*2^(146)
所以用10进制表示为0.000000
第二部分
经过*pfloat = 9.0
n中的值被改为浮点数,其二进制表示为
0 10000010 00100000000000000000000
其用10进制整型打印即为
*pfloat的值为9.000000