C语言 大小端问题、整型的存取、浮点数的存取


类型

整型类型包括:(有/无符号)int 、char 、short 、long 、longlong;

浮点数类型包括:float、double;

构造类型包括:数组、结构体、枚举、联合、指针

void是无类型(0字节),常用于做函数返回值,不可以定义变量,因为其类型不开辟内存空间;
void* 是个指针类型(4个字节)可以定义变量,但是不能对其进行初始化操作。

(signed) char(1个字节) -128 ~ 127(-128的二进制1000 0000)
unsigned char(1个字节) 0 ~ 255

int (4个字节) -231 ~ 231-1 (-2147483648~2147483647)
unsigned int (4个字节)0 ~232-1 (0~4294967295)

short(2个字节)-215 ~ 215-1(-32768~32767)
unsigned short (2个字节)0 ~ 216-1(0 ~ 65535)


大小端
在计算机中,一个字节对应一个地址,而寄存器宽度大于一个字节,所以存在地址安排(安置排序)问题,就出现了大小端的问题。

大端(存储)模式:(小大大)
数据的低位(权值低的位)保存在内存的高地址中。
小端(存储)模式:(小小小)
数据的低位(权值低的位)保存在内存的低地址中。

可以写一个小程序判断你的电脑是什么端?

int check_sys()
{
	int i = 1;
	return (*(char*)&i); //把i的地址强制转化成char*
}

同样可以利用共用体来判断

int check_sys()
{
	union
	{
	int i;
	char c;
	}un;
	un.i = 1;
	return un.c;  //共用体占用同一个内存空间
}

整型的存取
任何整数在计算机里都是按二进制的 补码 来存放的。

存整型:
1.负数:第一位是符号位,若是1则第一位不变取反再+1,得到补码。若是0则存二进制原码。
2.正数:原码、反码、补码都一样。
那么就是说,存数据的时候,可以不看类型直接存补码。

取整型:
1.整形提升:如果输出的类型所占字节大于变量本身的类型所占字节,那么就按变量原类型填满空缺位,是有符号类型那就补1,是无符号类型就补0;
2.输出时看读取数据的类型也就是输出类型,如果是无符号类型那就直接输出其二进制;如果是有符号类型,判断是否为负数,是负数就 -1->取反->输出,是正数就直接输出二进制。
在这里插入图片描述
看几个栗子:

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("%d,%d,%d",a,b,c);
	return 0;
}

a、b:
存:
原码:1000 0001
取反:1111 1110
+1:1111 1111 //存到计算机里的二进制码

取:读取类型是 有符号int型,需要整形提升, char有符号类型,填1.
整形提升:1111 1111 1111 1111 1111 1111 1111 1111
读取:最高位是1,负数
-1:1111 1111 1111 1111 1111 1111 1111 1110
取反:1000 0000 0000 0000 0000 0000 0000 0001
所以取到的a、b是-1

c:
存:
原码:1000 0001
取反:1111 1110
+1:1111 1111 //存到计算机里的二进制码

取:读取类型是 有符号int型,需要整形提升,unsigned char无符号类型,填0.
整形提升: 0000 0000 0000 0000 0000 0000 1111 1111
读取:最高位是0,正数,直接输出
所以取到的c是255

int main()
{
	char a = -128;
	printf("%u\n",a);
	return 0;
}

存:
原码: 1000 0000
反码: 1111 1111
+1: 1000 0000
取:
整形提升:有符号
1111 1111 1111 1111 1111 1111 1000 0000
输出类型无符号直接输出
输出结果是:4294967168

int main()
{
	char a = 128;
	printf("%u\n",a);
	return 0;
}

存:
原码:0 1000 0000

取:
整形提升:有符号
1111 1111 1111 1111 1111 1111 1000 0000
输出类型无符号,直接输出:4294967168

int i = -20;
unsigned int j = 10;
printf("%d\n",i+j);

存:
i:
原码:1000 0000 0000 0000 0000 0000 0001 0100
反码:1111 1111 1111 1111 1111 1111 1110 1011
+1:1111 1111 1111 1111 1111 1111 1110 1100
j:
原码:0000 0000 0000 0000 0000 0000 0000 1010
i+j:1111 1111 1111 1111 1111 1111 1111 0110
取:
有符号
-1: 1111 1111 1111 1111 1111 1111 1111 0101
取反:1000 0000 0000 0000 0000 0000 0000 1010
得到的是-10

unsigned int i;
for(i =9;i >= 0;i--)
{
	printf("%u\n",i);
}

无符号char型范围就是0 ~ 255,所以它是恒大于等于0;即是个死循环

short num = 32767;
short int a = num + 1;
printf("%d\n",a);

short的范围是 -32768 ~ 32767
a:
存:
原码:1111 1111 1111 1111+1 = 1 0000 0000 0000 0000
取:
整形提升:1111 1111 1111 1111 0000 0000 0000 0000
输出类型有符号
-1:1111 1111 1111 1110 1111 1111 1111 1111
取反:1000 0000 0000 0000 0000 0000 0000 0000
结果是-32768


浮点数的存取
浮点数的存储记住一个公式
(-1)s *M *2E
存储一个浮点数相当于存SME的二进制的相加的结果

float占用比特位
S1
E8
M23
double占用比特位
S1
E11
M52

S:存1或者0;表示浮点数的正负。
M:范围是 M>=1&&M<2 ;存储的时候为了节省空间不存储最高位的1,只存精度。相当于可以多存一位精度值。
E:因为E可以为负指数,用加减一个数表示会让计算更加简单。

8bit11bit
中间数1271032
存入时+127+1032
取出时-127-1032

E全为0:1-中间数,M不再加最高位的1,表示无穷接近±0的很小的数字。
E全为1:若M的有效数字全为0,则表示无穷大。
再举一个栗子:

9.0存取

1001.0-> 1.001*23-> (-1)0 * .001 * 23
S= 0; M = 1.001; E = 3+127 = 130;->1000 0010
二进制: 0 10000010 00100000000000000000000

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值