一、类型的基本归类
整形家族:
1.char :unsigend char 、signed char
2.short unsigend short[int]、signed short[int]
3.int unsigned int、signed int
4.long unsigned long[int]、signed long[int]
浮点型家族:
float、double
构造类型:
组类型、结构体类型、枚举类型、联合类型
指针类型:
int*、char*、float*、void*
空类型:函数的返回参数、函数的参数、指针类型
二、整形在内存中的存储:
2.1原码、反码、补码
三种表示方法有符号位和数值位,符号位0表示正数,1表示负数
原码:直接翻译
反码:符号位不变、其他位按位取反
补码:反码+1
结论:1.数据存放内存其实存放的是补码 2.正数的原码。反码、补码相同
实例:
#include<stdio.h>
int main()
{
int a = 20;
00000000000000000000000000010100 -a的原码、反码、补码
int b = -10;
10000000000000000000000000001010 -b的原码
11111111111111111111111111110101 -b的反码
1111 1111 1111 1111 1111 1111 1111 0110 -b的补码
ff ff ff f6
00000000000000000000000000010100
11111111111111111111111111110110
00000000000000000000000000001010 ->10
int c = a + b;
printf("%d\n", c);
return 0;
}
2.2大小端的介绍
大端(存储)模式:数据的低位保存在内存的高地址处。数据的高位保存在内存的低地址处。
小端(存储)模式:数据的低位保存在内存的低地址处。数据的高位保存在内存的高地址处。
实例:判断当前编译器使用的是大端存储还是小端存储
#include<stdio.h>
int check_sys()
{
int p = 1;
return *(char*)&p;
}
int main()
{
if (check_sys() == 1)//ASCII码值的比较
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
实例练习:
实例一:
#include <stdio.h>
int main()
{
char a = -1;
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111
//11111111 截断
//11111111111111111111111111111111
//11111111111111111111111111111110
//10000000000000000000000000000001 -> -1
signed char b = -1;
//同上-1
unsigned char c = -1;
//11111111
//0000000000000000000000011111111 ->255
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
实例二:
实例2:
#include <stdio.h>
//%u - 打印的是无符号整数,认为内存中对应的是一个无符号数
//%d - 打印的是有符号整数,认为内存中对应的是一个有符号数
int main()
{
char a = -128;
//10000000000000000000000010000000
//11111111111111111111111101111111
//11111111111111111111111110000000
//10000000
//00000000000000000000000010000000 ->128//err,
// 提升按照的是它的类型,而打印看的是它在内存中的存储,打印不影响它原来本身的提升
//11111111111111111111111110000000 ->4294967168 ok
printf("%u\n", a);
return 0;
}
实例三:
#include <stdio.h>
int main()
{
char a = 128;
//00000000000000000000000010000000
//10000000
//11111111111111111111111110000000 ->4294967168 ok
printf("%u\n", a);
return 0;
}
实例四:
#include<stdio.h>
int main()
{
int i = -20;
//10000000000000000000000000010100
//11111111111111111111111111101011
//11111111111111111111111111101100
unsigned int j = 10;
//00000000000000000000000000001010
//11111111111111111111111111101100
//11111111111111111111111111110110 i+j的补码
//11111111111111111111111111110101 i+j的反码
//10000000000000000000000000001010 i+j的原码 -> -10
printf("%d\n", i + j);
return 0;
}
补充:
char类型的取值范围:-128~127(图像法记忆)
unsigned char的取值范围是:0~255
short类型的取值范围:-32768~32767
unsigned short的取值范围:0~65535
实例五:
#include<stdio.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
//因为unsigned是无符号数,所以一定大于等于0,所以死循环
return 0;
}
实例六:
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;//-1 -2 -3 -4 ....-128 127 126..3 2 1 0,strlen遇到0就结束
}
printf("%d", strlen(a));//255
return 0;
}
实例七:
#include <stdio.h>
unsigned char i = 0;
int main()
{
for (i = 0; i <= 25; i++)//由于unsigned char取值范围是:0~255,所以死循环
{
printf("hello world\n");
}
return 0;
}
三、浮点型的存储:
IEEE754表示任意一个二进制浮点数V可以表示成下面的形式
(-1)^S*M*2^E
S:正数为0,负数为1(float和double都占用1个bit)
M:1<=M<=2,只保留小数位,个位数不保留,因为个位数都是1(float占用:8个bit,double占用:11个bit)
E:在原有的E的数值上+127(float占用:23bit,double占用:52bit)
1.不为全0或者全1:真实值
2.为全0:M的个位数不在补充,E=-126
3.为全1:表示的是+-无穷大的一个数
实例解析:
#include<stdio.h>
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);//9
//0 00000000 00000000000000000001001
//S=0 E=00000000~-126 M=0.00000000000000000001001
printf("*pFloat的值为:%f\n", *pFloat);//0.0
*pFloat = 9.0;
//9.0=1001.0=1.001*2^2
//S=0 E=129 M=001
//0 10000010 00100000000000000000000
//01000001000100000000000000000000 -> 1091567616
printf("num的值为:%d\n", n);//1091567616
printf("*pFloat的值为:%f\n", *pFloat);//9.0
return 0;
}