1.1、类型的基本归类
整型家族:
char
unsigned char
signed char
short
unsigned short[int]
signed short[int]
int
unsigned int
signed int
long
unsigned long[int]
signed long[int]
对于有符号的数据,最高位是符号位;对于无符号的数据,最高位是数据位
浮点数家族:
float
double
long double
构造类型:也叫自定义类型
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
指针类型:指针变量是用来存放地址的
int* pi
char* pc
float* pf
void* pv空类型:void表示空类型(无类型),通常用于函数的返回类型、函数的参数、指针类型
void test(void)
{
}
int main()
{
return 0;
}
2、整形在内存中的存储
2.1、原码、反码、补码
int main()
{
int b = -10;//在内存中存储的是补码 ff ff ff f6
return 0;
}
数字在内存中被存储为补码的原因:
使用补码可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路
int main()
{
unsigned int a = -10;
printf("%d\n", a);//%d是打印有符号数
printf("%u\n", a);//%u是打印无符号数,即使数字有符号,也会按照无符号数打印
return 0;
}
2.2、大小端介绍
大端字节序存储:把一个数据低位字节处的数据存放在高地址处,把高位字节处的数据存放在低地址处。如将0x11223344存储为11223344
小端字节序存储:把一个数据低位字节处的数据存放在高地址处,把高位字节处的数据存放在高地址处。如将0x1223344存储为44332211
写一个程序检测机器是大端存储还是小端存储
int check_sys()
{
int a = 1;
char* p = (char*)&a;
return *p;
}
int main()
{
int ret = check_sys();
if (ret == 0)
{
printf("大端\n");
}
else
printf("小端\n");
return 0;
}
2.3、练习
下列程序输出的是什么
int main()
{
char a = -1;// 原1000000000000000000000000000001
// 反1111111111111111111111111111110
// 补1111111111111111111111111111111 则字符a在内存中存储为11111111,整型提升后为1111111111111111111111111111111,signed char同理
signed char b = -1;
unsigned char c = -1; //无符号整型,11111111整型提升后为00000000000000000000000011111111,为255
printf("a=%d b=%d c=%d", a, b, c);
return 0;
}
int main()
{
char a = -128;
printf("%u\n", a); //%u-无符号10进制整型
//10000000整型提升后为11111111111111111111111110000000
return 0;
}
int main()
{
char a = 128;
printf("%u\n", a); //与上一题同理
//10000000整型提升后为11111111111111111111111110000000
return 0;
}
int main()
{
int i = -20;
//1000 0000 0000 0000 0000 0000 0001 0100-原
//1111 1111 1111 1111 1111 1111 1110 1011-反
//1111 1111 1111 1111 1111 1111 1110 1100-补
unsigned int j = 10;
//0000 0000 0000 0000 0000 0000 0000 1010-原
//0000 0000 0000 0000 0000 0000 0000 1010-反
//0000 0000 0000 0000 0000 0000 0000 1010-补
printf("%d\n", i + j);
return 0;
}
#include<Windows.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
//Sleep(1000);//延时1000毫秒
}
return 0;
}
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i; //i=0,1,2,3...999
//a=-1,-2,-3...-128,127,126...3,2,1,0...
}
printf("%d", strlen(a));//strlen要算的是数组长度,计算0或/0前面的元素个数
return 0;
}
unsigned char i = 0;//无符号字符内容为0-127
int main()
{
for (i = 0; i <= 255; i++)//i无法到达255,死循环
{
printf("hello world\n");
}
return 0;
}
3、浮点型在内存中的存储
3.1、浮点数存储的例子
int main()
{
int n = 9; //整数9在内存中存储为0000 0000 0000 0000 0000 0000 0000 1001,以浮点数读取方式读出后为0
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);//9
printf("pFloat的值为:%f\n", *pFloat);//0.000000
*pFloat = 9.0; //浮点数9.0在内存中存储为0 10000010 00100000000000000000000,以整数读出为1091567616
printf("n的值为:%d\n", n);//1091567616
printf("pFloat的值为:%f\n", *pFloat);//9.000000
return 0;
}//此例表明整型和浮点型的存储方式不同
3.2、浮点数存储规则:(-1)^S * M * 2^E
例 5.5二进制存储为101.1,则存储为(-1)^0 * 1.011 * 2^2
9.0二进制存储为1001.0,则存储为(-1)^0 * 1.001 * 2^3
因为M的小数点左边第一位总为1,则可以省略,只记录小数点后的数字
在实际存储中,E可能出现负数,对于8位的E,需要加一个中间数127,对于11位的E,加中间值1023
int main()
{
float f = 5.5;
//S=0;
//M=1.011
//E=2 + 127 = 1000 0001
//0 10000001 01100000000000000000000
//0100 0000 1011 0000 0000 0000 0000 0000
//0x40b00000
return 0;
}
int main()
{
float f = 0.5;
//(-1)^0 * 1.0 * 2^-1
//S=0
//M=1.0
//E= -1+127 = 01111110
//0 01111110 0000000000000000000
//0011 1111 0000 0000 0000 0000 0000 0000
//0x3f000000
return 0;
}
3.3、浮点数取出规则
1、E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
2、E全为0:指数E为1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxx的小数。这样做是为了表示±0,以及接近于0的数字
3、E全为1:这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位S)。