数据的储存

1. 数据类型的介绍

char//字符型   1字节数
short//短整型   2
int//整型      4
long//长整型    4
long long//更长的整型  8
float//单精度   4
double//双精度   8

整型

一般情况下默认 int是signed int。

正数的原码,反码,补码相同,负数的原码反码补码规则如下:

#include<stdio.h>
int main()
{
	int a = 20;//14 00 00 00
	int b = -10;//f6 ff ff ff//11110110 11111111 11111111 1111111111111111
	//正数的原码,反码,补码相同,负数的原码反码补码规则如下
	//原码:10000000 00000000 00000000 00001010
	//反码:11111111 11111111 11111111 11110101//其余取反符号位不变
	//补码:11111111 11111111 11111111 11110110//取反加1

	char c1 = 5;//05 00 00 00 
	unsigned char c2 = 5;//05 00 00 00 
	short s1 = 10;// 0a 00 00 00
	unsigned s2 = 10;//0a 00 00 00 
	int i1 = 20;//14 00 00 00
	unsigned int i2 = 20;//14 00 00 00
}

对于整型来说:数据存放内存中的是补码。
使用补码可以将符号位和数值位统一处理。(cpu中只有加法)

    int q = 1;
	int w = 1;
	int e = q - w;//看作e=q+(-w)
	//q补码:00000001
	//-w原码:10000001    反码:11111110    补码:1111111
	//计算加法 00000001    
	/ 11111111
	//=======1   00000000 将1截断得   e=0;

符号位不变,原到补为取反加一
符号位不变,补到原为取反加一
减一取反也行
整型提升:

#include<stdio.h>
int main()
{
	char a = -1;//     -1     的原码1000——0001———反码1111——1110————补码1111——1111;截断a放置为11111111;a再整型提升为1111——1111提升是向前补符号位
	signed char b = -1;//与a相同为-1
	unsigned char c = -1;//     -1     的原码1000——0001———反码1111——1110————补码1111——1111;截断c为11111111;c整型提升高位补0;0000————————1111//最高位是零即为正数//8个1为255
	printf("%d %d %d", a, b, c);//-1 -1 255
	return 0;
}

原因:有符号整型提升时最前面会补1,为11111111——11111111=-1;无符号整型提升时前面会补0,为00000000——11111111=255;
截断与提升
截断是将整型二进制数高位相应的字节截断
提升是将该变量中二进制数高位补满符号位
例如:

int main()
{
	char a = -128;//原10000000 00000000 00000000 10000000
				  //反11111111 11111111 11111111 01111111
	              //补11111111 11111111 11111111 10000000
				  //a 10000000//截断是截断前面的
				  //a 11111111 11111111 11111111 10000000整型提升

	printf("%u\n", a); //%u无符号10进制整数//4294967168
	return 0;
}
int main()
{
	char a = 128;//a=10000000就是-128
				 //char类型的取值范围在-128————127 unsigned char的范围是0——255
	printf("%d\n%u\n", a, a); //-128 4294967168
	//char类型从000000000==0到01111111=127 到100000000=-128 到11111111=-127
	return 0;
}
int main()
{
	int i = -20;		//原10000000 00000000 00000000 00010100
						//反11111111 11111111 11111111 11101011
				//i		//补11111111 11111111 11111111 11101100 
	unsigned int j = 10;//原00000000 00000000 00000000 00001010
				//j		//原反补相同					
	printf("%d", i + j);//补11111111 11111111 11111111 11110110//储存的i+j
	printf("\n%u", i + j);//将用无符号方式解二进制得4294967286
	return 0;//原10000000 00000000 00000000 00001010	解出-10的原码 
}
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;//10000001加任意
	}
	printf("%d", strlen(a));
	//从-1到-128到127到0
	return 0;
}

在这里插入图片描述

  • 大小端存储
    1.大端存储模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。例如:x86,ARM,DSP
    2.小端存储模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。例如:KEIL,C51
    在这里插入图片描述
    有些ARM处理器还可以由硬件来选择。
#include<stdio.h>
int main()
{
	int a = 0x11223344;// 44 33 22 11
	//由于11是高位放在高地址处了,所有改编器下为小端存储
	return 0;
}

判断大小端:

int main()
{
	int a = 3;//大端0——————00000110;小端000000110——————————0;
	//将它的前两个字节拿出来——大端:0000000000;小端00000110;
	short b = (short)a;
	char* p = (char*)&a;
	*(char*)&a;//解引用已经被char指针指向的a的地址
	printf("%d\n", *p);
	if (b != 0)
		printf("该编译器为小端存储。\n");
	else
		printf("该编译器为大端存储。\n");
	printf("%d", b);
	return 0;
}

当然如果上述例子中a=1时会更方便判断和构造判断函数返回参数,

浮点型

#include<stdio.h>
int main()
{
	int n = 9;//n=00 00 00 09
	float* pFloat = (float*)&n;//浮点型指针指向浮点型n的地址
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	*pFloat = 9.0;//0 10000010 00100000000000000000000
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);//float n=00 00 10 41
	return 0;
}

在这里插入图片描述
浮点数V=(-1)s m 2e;
如:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2。

2E是因为,是因为这个是个二进制数
1<=M<2,所以说m=1.xxxx可以写为.xxxx多保留一位。**

  1. 对E的分析:
    1.存E
    (由于E存在负数,但是E的存储是无符号二进制数)需要对E加上一个中间值
    八位加127;十一位加1023;
    (2的八次方=255;2的十一次方=2048)
    2.取E
    1)E全为1
    表示2的128次方或2的1024次方无穷大(正负取决于S)
    2)E全为0
    表示2的负127次方或2的负1023次方,表示无穷小,M将不再加上1,而是直接还原为0.xxxx,这样表示无穷小的±0;
    3)E不全为1也不全为0:
    这是需要根据八位或十一位减去127或1023得到真实值,再在M上加第一位1.
int main()
{
	float a = 5.5;//为(-1)**0*5.5*10**0=(-1)**0*101.1*2*2;    
	//0 10000001 01100000000000000000000
	//00 00 b0 40小端存储 40 b0 00 00
	return 0;
}
  1. 单精度
    S/E/M=1/8/23 (bit)在这里插入图片描述

  2. 双精度
    S/E/M=1/11/52(bit)
    在这里插入图片描述

自定义类型(构造类型)

数组类型
类型和数组大小改变时,类型也是一种改变。

结构体类型(struct)

将军走此小道

枚举类型(enum)
1.枚举顾名思义就是一一列举。
2.把可能的取值一一列举。
列如:
这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。

#include<stdio.h>
enum day
{
	Mon,
	Tues,
	Wed=10,
	Thur,
	Fri,
	Sat,
	Sun,
};//和#define差不多
int main()
{
	printf("%d\n", Mon);//0
	printf("%d\n", Tues);//1
	printf("%d\n", Wed);//10
	printf("%d\n", Thur);//11
	printf("%d\n", Fri);//12
	return 0;
}

枚举类型的优点:
我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
  3. 防止了命名污染(封装)(如将1可用Mon替代)
  4. 便于调试
  5. 使用方便,一次可以定义多个常量
    ##联合类型(union)
    联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)

联合体大小的计算(也满足对齐)

typedef union sz
{
	char str[5];//对齐数为1
	int a;//对齐数为4
}sz;//1*5+3与4中最大数=8
int main()
{
	printf("%d", sizeof(sz));
	return 0;
}

也可以用来求大小端存储

typedef union  St
{
	char a;
	int i;
}St;
int main()
{
	St s;
	s.i = 258;//1       00000010
	if (s.a != 0)
		printf("小端存储。\n");
	else
		printf("大端存储。\n");
	return 0;
}

空类型

void表示空类型(无类型)
通常适用于函数的返回类型,函数的参数,指针类型。

void f(void)
{;}
void*p;//一种没有具体类型的指针
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值