数据在内存中的存储(上:整形篇)

一.数据类型分类

数据在内存中,主要以两种形式存储

1.整形家族

  • char:  signed char,unsigned char 因为字符存储的是ASCII码值,所以也归于整形
  • short:signed short,unsigned short
  • int:signed int,unsigned int
  • long:signed long,unsigned long

2.浮点型家族

  • float
  • double

其他还有三种类型

3.构造类型

  • 数组类型
  • 结构体类型
  • 枚举类型
  • 联合类型

4.指针类型

int*,char*,float*,void*

5.空类型

void

通常用于:函数的返回类型void func(),函数的参数void func(void),指针类型(void*p)

二.整形在内存中的存储

整形可以变为原码,反码,补码存储在内存中

存储可以用"大端存储"或者"小端存储"这两种方式

1.原码,反码,补码

这三种就是一个整形用二进制表示的方法

这三种方法都分有“符号位”和”数值位“两部分,正数的符号位是‘1’,负数的符号位是‘0’

  • 正数

原码,补码,反码都相同

  • 负数

原码:即整形二进制表达方式

反码:原码符号位(0)不变,其他数值位按位取反

补码:反码+1

最终,在内存中存放的是补码


2.大小端

数据的高低位:

举一个例子,11的二进制表示为

10000000000000000000000000001011
313029282726252423222120191817161514131211109876543210

变成二进制,一共32个比特位0—31
存储的四位有效数据:1011

即1*2^0  +  1*2^1  +  0*2^3  +  1*2^4

1011这四个数,就代表数据的低位,详细见表格

不难发现数据的高位在前,低位在后


内存的高低地址:

00000000

内存低地址在前,高地址在后


现在我们已经知道了数据的高低位和内存的高低位判断,下面就让我们来看大小端这两种存储方式的不同

大端存储:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中

小端存储:数据的低位保存在内存的低地址中,数据的高位保存在内存的高地质中

大多数机器存储方式为,小端存储

3.关于整形存储的练习题

在做题前来看看singed和unsigned的区别

有符号,就是大家常见的整形类型,也分符号位和数值位

无符号,这是没有符号位,只有数值位

一般char,short,int,long都表示有符号,默认前面加sigend

unsigned char/short/int/long表示无符号

代码一:
#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;
}
有关a
  • 1.算出a=-1的二进制:

原码:1000 0000 0000 0000 0000 0000 0000 0000 0001

反码:1111  1111 1111  1111   1111  1111 1111  1111 1110

补码:1111  1111  1111  1111  1111  1111 1111  1111  1111

  • 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃   

截断补码:1111 1111

  • 3.打印为%d,需要整形提升,提高到32位。有符号补1,无符号补0。有符号。

整形提升补码:1111 1111 1111 1111 1111 1111 1111 1111

  • 4.最后别忘了恢复原码:补码-1,取反

打印的原码:1000 0000 0000 0000 0000 0000 0000 0001   //符号位不变

  • 5.变成十进制

打印数字:a=-1

有关b

char与signed一般相同,所以同上

打印数字:a=-1

有关c
  • 1.算出a=-1的二进制:

原码:1000 0000 0000 0000 0000 0000 0000 0000 0001

反码:1111  1111 1111  1111   1111  1111 1111  1111 1110

补码:1111  1111  1111  1111  1111  1111 1111  1111  1111

  • 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃   

截断补码:1111 1111

  • 3.打印为%d,需要整形提升,提高到32位。有符号补1,无符号补0。符号。

整形提升补码:0000 0000 0000 0000 0000 0000 1111 1111  //高位为0,正数,原码即补码

打印的原码:0000 0000 0000 0000 0000 0000 1111 1111 

  • 4变成十进制

打印数字:c=255  

看结果


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

解释:    %u指以十进制形式打印无符号整形

区别一下%d:指以十进制形式打印有符号整形

解题

  • 1.a=-128的二进制:

原码:1000 0000 0000 0000 0000 0000 0000 1000 0000

反码:1111  1111 1111  1111   1111  1111 1111  0111 1111

补码:1111  1111  1111  1111  1111  1111 1111  1000  0000

  • 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃   

截断补码: 1000  0000

  • 3.打印为%u,需要整形提升,提高到32位。有符号补1,无符号补0。有符号。

整形提升补码/原码:1111 1111 1111 1111 1111 1111 1000  0000

  • 4.
  • 5.变成十进制

打印数字:a=4294967168

看看结果


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

128在发生截断后,高位也被丢弃,正数负数没区别了,和上题一样的结果

代码四
int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j);
  • 1.i=-20的二进制:

原码:1000 0000 0000 0000 0000 0000 0000 0001 0100

反码:1111  1111 1111  1111   1111  1111 1111  1110 1011

补码:1111  1111  1111  1111  1111  1111 1111  1110  1100

  • 2.j=10的二进制:

原码/反码/补码:0000 0000 0000 0000 0000 0000 0000 0000 1010

  • 3.相加,

补码:i+j=1111  1111  1111  1111 1111  1111  1111 0110

原码:i+j=1000 0000 0000 0000 0000 0000 0000 1010

  • 4.打印十进制

打印数字:a=-10

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

对于这个循环,可以发现,i是无符号数,没办法降到0以下,-1的无符号数这样写:
1000 0000 0000 0000 0000 0000 0000 0001

最前面的1不是符号位,是数值位,这时i就是很大的数

从很大的数开始递减

是一个死循环

 代码六
int main()
{
    char a[1000];
    int i;
    for(i=0; i<1000; i++)
   {
        a[i] = -1-i;
   }
    printf("%d",strlen(a));
    return 0;
}

char它被截断后只剩8个比特位,它没办法做到32个比特位那样广阔的选择范围,最后它的数值在-128——127之内,这是说的char的情况,strlen是数\0前面的字符数,最大只能到达255,所以打印的255

代码七
#include <stdio.h>
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0;
}

 是个死循环,因为i是char类型,最大只能达到255

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值