详析数据在内存中的存储_long 64位 存储方法

以下程序会输出什么?
#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf(“a=%d,b=%d,c=%d”,a,b,c);
    return 0;
}

相信很多朋友看到这道题后有所疑惑:这能有什么问题,输出应该是-1,-1,-1呀?

2e6b84b63fee4afcaa7ea0ffaf91fe6b.gif

这种疑惑便是今天要讲到的细节知识。

其实它的答案是-1 -1 255.

b4af3feef73f469c8c25bcf03b04496d.gif


为了便于理解,我们先讲解数据类型:

数据类型
|                           char |              字符数据类型    1byte |
|                          short |                      短整型        2byte |
|                            int |                        整型          4byte |
|                          long |                      长整型       4/8byte |
|                        long long |                  更长的整型      8byte |
|                          float |                 单精度浮点数    4byte |
|                         double  |                 双精度浮点数    8byte |

long: 在32位机器下是4byte,在64位机器下是8byte.

整型家族

按照有无符号来分类:

charunsigned char signed char
shortunsigned short signed short
intunsigned int signed int
longunsigned lnog signed long
long longunsigned long long[int] signed long long[int]

特殊点:字符的本质是ASCII值,所以属于整形。除此之外,char到底是unsigned char还是signed char是标准为定义的,但大部分编译器,如VS下默认是有这两种类型区分的。


这里提出疑问:有无符号的区分有什么意义呢?

1.为了创建变量的时候符合实际情况。比如身高、体重没有负值。

2.有无符号决定了数值二进制位最高位的0或1具有符号意义还是数值意义。


步入正题,整形数据在内存中到底是如何存储的?

整形数据在内存中如何存储?

整形数据在内存存放的是二进制,并且是数据的补码,但调试的过程中我们看到的又是16进制数,这里不要混淆,是因为如果以二进制位显示数据过长,为了便于观察采取16进制显示。

举例:

十进制的21:

二进制表示:0b10101

八进制表示:025

十进制表示:21

十六进制表示:0x15

为什么数据在内存中必须是补码存储呢?

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。

举例:

我们要计算1+(-1):


如果以两者的原码进行计算(假设数据是8位):

1的原码: 0000 0001

-1的原码:1000 0001

结果为:  1000 0001——>-2  显然是错的.


如果以两者的补码进行计算(假设数据是8位):

1的补码: 0000 0001

-1的补码:1111 1111

结果为: 1 0000 0000——>最高位1溢出,最终得到0正确.

针对最开始的题,我们还需要了解数据表示范围:

数据范围

char型:

a5690ab9e744413c9937599d898b1bc0.png

如图为char型数据可表示范围:

有符号的:-127~128

无符号的:0~255

其他类型同理.


至此,我们可以讲解起初的题了.(先文字讲解,后图解)

首先题中开始赋值时给字符a,b,c都赋的是整形数值(32bit);

char a = -1
1000 0000 0000 0000 0000 0000 0000 0001 —  -1的补码
1111 1111 1111 1111 1111 1111 1111 1110 —  -1的反码
1111 1111 1111 1111 1111 1111 1111 1111 —  -1的原码
由于32位太长,char型只有8位,因此将-1放进char内部时会发生截断
1111 1111  —  a
打印的时候是%d形式,因此又要发生整形提升,
提升后的数又会被内存看做补码进行处理,打印的是最后的原码
提升———高位按照原来的符号位来补
1111 1111 1111 1111 1111 1111 1111 1111 — 补码
1000 0000 0000 0000 0000 0000 0000 0000 — 反码
1000 0000 0000 0000 0000 0000 0000 0001 — 原码 ----->   -1


unsigned char c = -1
1000 0000 0000 0000 0000 0000 0000 0001 —  -1的补码
1111 1111 1111 1111 1111 1111 1111 1110 —  -1的反码
1111 1111 1111 1111 1111 1111 1111 1111 —  -1的原码
继续截断,再整型提升
1111 1111 — c
0000 0000 0000 0000 0000 0000 1111 1111 — 补码 <=> 原码
结果为255

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值