数据在内存中的存储1:整形(char,short,int...)的补码

简介: 在整形家族中

①在整形家族中有:


char (一个字节)

   unsigned char

   signed char

short(int 省略)(两个字节)

   unsigned short

   signed short

int(四个字节)

   unsigned int

   signed int

long(int 省略)(四个字节)//在早期老设备int是两个字节,所以称之为长整形,而现在long与int长度一致

   unsigned long

   signed long

long long 同(八个字节)

注意:只有char类型的数据类型由不同编译器环境决定默认为无符号还是有符号

其他均默认为有符号,vs环境下char为有符号


②整形在内存中存储:补码(二进制的形式)(小提一手)



在vs中,调试内存窗口这里,是按字节为单位有序排列(这里是按十六进制(容易看),ox为十六进制前缀)


(a~f代表10~15)


两个十六进制位刚好代表一个字节八个二进制位(通过数学知识,我们只需要在对应的每八个二进制与对应的每两个十六进制相互转化就好)(其他进制就没有这么好的性质)


补码来运算,非常的方便,最主要是不影响结果


③符号与无符号:


unsigned 无符号:没有符号位,恒为正


signed 有符号:补码首位为1则为为负


其他进制的数的正负取决于首位,例如十六进制,首位0~7则位正,8~15为负,(一半数为正,一半数为负)


结合类型的字节数,导致他们拥有了一个“闭环的”取值范围


(例如char)



其他类型可类推(超出范围就会截断,-这导致出现了取值范围)


④整形在内存中以补码的形式存储.


对于正数和无符号数,他们的原码反码补码相同;


对于负数,


例如  (int)-1


原码(给人看的,直接得到到二进制数)(补码取反加一or补码减一取反)


10000000000000000000000000000001


反码(除了符号位,按位取反)


1111111111111111111111111111111111110


补码(计算机内存中看到的,计算机认识的,计算机识别的)(原码取反加一)


1111111111111111111111111111111111111


(如果强制类型转化位unsigned int 则计算机直接识别到的是补码,直接认为是正数)


补充:10000000000000000000000000000000(-2147483648)的原码是三十三位的,但是没关系,内存中是三十二位就好,毕竟字节大小限制的是补码,因为存放的是补码。


注意:其他位数的什么什么码要转化为二进制看


补充:在计算过程中,遇到整形提升和算术转化和截断甚至移位操作符,位数上升(或者补位),有符号整形补符号位,无符号补0,计算过程保持用补码,并且算术表达式最低类型为int,计算结果根据最终要存放在哪个类型中决定补充还是截断。(有时通过闭环取值范围能很好的得到结果)


额外内容:大小端字节序


(大端模式)就是数据的低位存放在高地址处,数据的高位存放在低地址处


(小端模式)就是数据的高位存放在高地址处,数据的低位存放在低地址处(VS环境)



以字节为单位从左往右地址递增,位的值大小也递增(符合习惯)(习不习惯不重要,记住这个规矩就好,并且一些编译器是大端,与此相反)(这跟指针的加法和解引用有关)


下面是一个函数来判断编译器是大端还是小端


void judge()
{
    int i=1;
    if(*((char*)&i))
        printf("小端\n");
    else
        printf("大端\n");
}
//其他序列类型被淘汰了

练习:


#include<stdio.h>
int main()
{
    unsigned char c=-1;
    printf("%d",c);
    return 0;
}

这里,-1为整形,则补码为11111111111111111111111111111111,但是是截断后为11111111(无符号255),然后要变为有符号整形int,要补充0,得到00000000000000000000000011111111,就是255.


#include<stdio.h>
int main()
{
   char a=-128;
    printf("%u",a);
    return 0;
}

这里,-128为10000000,整形提升补的是符号位1,为11111111111111111111111110000000,然后被认为是无符号打印出来,就是4294967168

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

这里,把128(......10000000)放到char里面去,(截断后)是-128,而打印成无符号,就跟上一道题一样,先补上符号位1,然后被看做是无符号打印出来。


int main()
{
    int i=-20;
    unsigned int j=10;
    printf("%d",i+j);
    return 0;
}

这里,-20为10000000000000000000000000010100


       补码  ->111111111111111111111111111111101100      


           10为00000000000000000000000000001010


-20的补码被看作了无符号,然后与10相加,后为111111111111111111111111111111110110  


但是打印的时候计算机识别这个补码,打印为有符号(通过计算出原码知道是-10)


就是说:(需要补位的补位,截断的截断之后)不用管送到占位符那的那个补码的前世今生,根据占位符读这个码,得到多少就是多少。


最后注意了

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

这是一个死循环,因为0-1后,由于是无符号,它还是大于等于0的!


目录
相关文章
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**问题简介:** 客户在使用触发器将表 A 中 varchar(4000 char) 列的数据复制到表 B 时,发现表 B 中的数据出现乱码且与表 A 不一致。此问题影响所有 YashanDB 版本,原因是 YashanDB 在处理触发器场景下的大长度 varchar 数据复制时存在机制错误。为避免该问题,建议将列长度修改为 varchar(2000 char) 或更小。数据正确性无法保证,需谨慎处理。 **验证方法:** 可通过创建表 A 和 B 及相应触发器进行测试。
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为&#39;0&#39;或&#39;1&#39;,查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
数据库连接 PHP 数据库
【YashanDB知识库】PHP使用ODBC驱动无法获取长度为256char以上的数据
【YashanDB知识库】PHP使用ODBC驱动无法获取长度为256char以上的数据
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**简介:** 某客户在使用触发器将表 A 的 varchar(4000 char) 列数据复制到表 B 时,出现数据乱码且不一致的问题。经分析,YashanDB 在处理触发器场景下的 varchar(4000 char) 列数据复制时存在机制错误,影响所有版本。建议将列长度修改为 varchar(2000 char) 或更小以规避问题。通过特定 SQL 可验证该问题是否存在。
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
【Java基础面试五】、 int类型的数据范围是多少?
这篇文章回答了Java中`int`类型数据的范围是-2^31到2^31-1,并提供了其他基本数据类型的内存占用和数值范围信息。
【Java基础面试五】、 int类型的数据范围是多少?
|
存储 C语言
使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小
【10月更文挑战第13天】使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小。
785 1
|
存储 缓存 Java
int 和 Integer 哪一个占用更多内存?
【8月更文挑战第21天】
706 0
|
存储 自然语言处理 Java
Java中的字符型数据(char)
Java中的字符型数据(char)
1265 0