数据类型介绍
大致分为两类
char int short float long double…
数组 结构体 枚举 联合体
#include
int main()
{
//数组也是一种自定义类型
int arr[10] = { 0 };
printf("%d\n", sizeof(arr)); //40
printf("%d\n", sizeof(int [10])); //40
int a = 10;
sizeof(int); //可以的
sizeof(a); //可以的
//那么问题来了,数组的类型是什么呢?
//数组的类型,就是数组去掉数组名剩下的部分
//比如上述对数组的声明 int arr[10],那么数组的类型就是int [10]
}
后续再进行介绍
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点型
double //双精度浮点型
char占一个字节,并不是说char占有一个字节,是char所声明的变量占据一个字节的大小,类型是不会占据空间大小的。
int *pi;
char *pc;
float *pf;
void *pv;
void表示空类型(无类型)
通常用于函数的返回值类型,函数的参数,指针类型
#include
void test()
{
printf("hehe");
}
int main()
{
test(20);
return 0;
}
//屏幕上打印的结果是hehe,虽然test函数实际上是没有参数的,但是在主函数调用test函数时候,还是传了参数,但是是没有任何影响的。
//你传是你的事情,我接不接受是我的事情。
//但是如果没有参数的话,最好还是在test函数的括号中加一个void,声明这个函数是没有参数的。
#include
int main()
{
int a = 0x11223344;
//0x11223344放在a里面是刚刚好的
//因为11是一个字节,22是一个字节,33是一个字节,44是一个字节
//通过监视看:转换到16进制,观察到a的值为0x11223344
//通过内存看:输入&a,可以观察到,a显示为44332211
return 0;
}
整数在内存中的存储首先要了解原码,反码,补码。
三种表示方法均有符号位和数值位,符号位都是用0表示正,用1表示负,而数值位,三种表示方法各不相同
#include
int main()
{
int a = -10;
//10000000000000000000000000001010 --原码
//11111111111111111111111111110101 --反码
//11111111111111111111111111110110 --补码
//fffffff6 ---补码转换成16进制的样子
//但是在内存中&a显示的结果是f6ffffff
}
#include
int main()
{
//加入说我想算一个1-1的结果是多少
//但是遗憾的是,计算机不能算减法
//那我只好把减法转换为加法的形式
//1 - 1;
1 + (-1);
//如果按原码来计算的话
// 1的原码
//00000000000000000000000000000001
//-1的原码
//10000000000000000000000000000001
//两个码相加的结果为
//10000000000000000000000000000010
//如果按照原码直接相加的话,结果就为-2,这显然是不正确的
//所以科学家们推出了补码的概念
//用补码来算的时候,可以算出正确的结果
}
针对于为什么存的是补码
比较专业的解释是:在计算机系统中,数值一律用补码来表示都和存储。原因在于。使用补码可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法处理器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
(用补码可以把数值位和符号位一起来运算,就不牵扯纠结到底最高位要不要加的问题了)
如下所示,看的出来数字在内存中是到这存储的,那么问题来了,为什么是到着存储的
#include
int main()
{
int a = 0x11223344;
//0x11223344放在a里面是刚刚好的
//因为11是一个字节,22是一个字节,33是一个字节,44是一个字节
//通过监视看:转换到16进制,观察到a的值为0x1223344
//通过内存看:输入&a,可以观察到,a显示为44332211
return 0;
}
大端:把一个数据的低位字节序的内容存储到高地址处,高位字节序的内容存储到低地址处。(是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中)
小端:把一个数据的低位字节序的内容存储到低地址,高位字节序的内容存储到高地址(是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中)
百度:
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序
//解题思路:
//我们可以通过把1存在内存中,然后通过看他的存储形式,我们来判断当前机器到底是大端还是小端
//1的16形式的格式为00000001
//如果存储形式是01000000那么就是小端
//如果存储形式是00000001那么就是大段
//我们可以通过读取第一个字节的内容,来判断到底是大端还是小端,想要读取一个整形的第一个字节,那么存储在char*类型的变量中就可以了。
#include
int main()
{
int a = 1;
char* pa = (char*)&a;
if (*pa == 1)
printf("小端");
else
printf("大端");
return 0;
}
//封装成一个函数
#include
int check_system()
{
int a = 1;
char* pa = (char*)& a;
if (*pa == 1)
return 1;
else
return 0;
}
int main()
{
int ret = check_system();
if (ret == 1)
printf("小端");
else
printf("大端");
return 0;
}
#include
struct Stu
{
char name[20];
int age;
};
union Un
{
int i;
char c;
}; //联合体类型
int main()
{
union Un u = { 0 }; //u为联合体对象
printf("%d\n", sizeof(u)); //结果为4
printf("%p\n", &u);
printf("%p\n", &(u.i));
printf("%p\n", &(u.c));
//三个的地址是一模一样的,说明i和c占用同一块空间
//所以联合体又叫共用体,共用体的意思就是我的成员要共用同一块空间
//那么我给i里面放东西c就会发生变化
//我给c里面放东西,i也会发生变化
//c是i占的四个字节中的第一个字节,这也解决了大小端算法的另一种解法问题
return 0;
}
#include
int check_system()
{
union Un
{
int i;
char c;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret = check_system();
if (ret == 1)
printf("小端");
else
printf("大端");
return 0;
}
#include
int main()
{
char a = -1;
signed char b = -1;
//char和signed char其实是一样得,所以前两个得结果一定是一样的
//-1的补码为:11111111111111111111111111111111
//保存到char中为11111111
//反码为:11111110
//原码为:10000001 --所以说前两个的结果为-1 和 -1
//有符号的类型,高位所需要补的是符号位
unsigned char c = -1;
//c放在内存中 11111111---补码
//又因为c是无符号数,所以给c的高位补0
//00000000000000000000000011111111 -- 补码
//又因为最高位是0,所以说为正数,正数的原,反,补相同
//所以c的结果为255 8个1的结果为255
printf("a=%d,b=%d,c=%d", a, b, c);
//-1 -1 255
return 0;
}
#include
int main()
{
char a = -128;
//10000000000000000000000010000000 原码-- -128
//11111111111111111111111101111111 反码
//11111111111111111111111110000000 补码
//但是只能存8个比特位,结果为10000000
//需要进行整形提升
//提升的时候需要看原来的符号位,全部补成1
//结果为11111111111111111111111110000000 --补码
//又因为是无符号数,所以原码,反码,补码全部相同
//所以就得到了结果:4294967168
printf("%u\n", a);
return 0;
}
#include
int main()
{
char a = 128;
printf("%u\n", a);
return 0;
}
//char的范围是-128~+127,所以char是无法表示+128的
#include
int main()
{
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
//10000000000000000000000000010100
//11111111111111111111111111101011
//11111111111111111111111111101100
//00000000000000000000000000001010
//11111111111111111111111111110110
//11111111111111111111111111110101
//10000000000000000000000000001010
//-10
return 0;
}
#include
int main()
{
unsigned int i;
//无符号的数,是没有负数的
//判断条件为i>=0,但是无符号的,i>=0是永恒成立的
//所以结果为死循环
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
#include
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
//什么时候遇到\0,长度就是多少,参考char的范围的哪个圆圈
//所以结果为255
return 0;
}
#include
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++)
{
printf("hello world\n");
}
return 0;
//这个程序会死循环
//unsigned char 的范围就是0-255,所以会死循环
}
常见的浮点数:
3.1415 1E10(为科学计数法,表示的是1.0*10^10),浮点数家族包括float,double,long double类型。
float的范围定义在float.h中
char的范围:-128~=+127
unsigned char的范围为:0~255
根据IEEE(电器和电子工程协会)754,任意一个二进制浮点数v可以表示成下面的形式:
eg:
5.5在内存中的存储
首先将它写成二进制的格式
101.1
1.011*2^2
所以就为
(-1)^0*1.011*2^2
所以
S=0
M=1.011
E=2
举个例子
5.5在内存中的存储
最高位为0
中间的8位加上127,结果为129 10000001
小数点后为011补齐为01100000000000000000000
所以5.5为
01000000101100000000000000000000
#include
int main()
{
int n = 9;
//9存在内存中,存储的时他的补码
//00000000000000000000000000001001
float* pFloat = (float*)& n;
//要把一个整形,转换层成一个浮点型,那么现在就来转换一下
//0 00000000 00000000000000000001001
//又因为上述浮点型的存储中E全为0,所以这个数字是一个无限接近于0的数字 ,所以打印的结果为0.000000
printf("n的值为:%d\n", n);
//以整形的形式存入,再以整形的形式取出,那么结果当然还是整形了,所以说结果为9;
printf("*pFloat的值为:%f\n", *pFloat);
//要把一个整形,转换层成一个浮点型,那么现在就来转换一下
//0 00000000 00000000000000000001001
//又因为上述浮点型的存储中E全为0,所以这个数字是一个无限接近于0的数字 ,所以打印的结果为0.000000
*pFloat = 9.0;
printf("n的值为:%d\n", n);
//以浮点数的形式存进去,以浮点数的形式往出拿
//先将9写成二进制的形式
//1001.0
//1.001*2^3;
//0 100000010 00100000000000000000000 --补码
//整数,原,反,补相同
//所以结果为010000001000100000000000000000000 --结果为1091567616
printf("*pFloat的值为:%f\n", *pFloat);
//以浮点数形式存进去,再以浮点是结果拿出来,结果是不会变化的
//结果为9.000000
return 0;
}