数据在内存中的存储的规则

数据在内存中存储的规则
数据在内存中的存储为二进制
整形在内存中有三种形式,原码、反码、补码
整数由两种形式组成
无符号位的原码反码补码相同
有符号位分为最高位和数值位组成

正数的原反补相同
负数的三种方法各不相同
原码:直接将数值按照正负数翻译出来的二进制得到的就是原码。
反码:将原码的符号位不变,其他的依次按位取反得到反码
补码:反码+1得到的补码

大端字节序和小端字节序概念

小端字节序存储:一个数据的低位字节数据,存放在内存到的低地址处,高位字节的数据,存放在内存中高地址处
大端字节序存储:第一个数据的低位字节数据存放在内存的高地址处,高位字节的数据存放在内存中低地址处

int main()
{
int a=0x11223344;
//11 22 33 44
//这种存储方式是大端字节序
//44 33 22 11
//这种存储方式是小端字节序存储
//一个16进制位可以换四个二进制位
return 0;
}

为什么会有大小端
因为在计算机中,我们是以字节为单位,每一个的地址单元都对应一个地址,1个字节中有8个bite位

1.写一个代码判断机器是大端还是小端:

#include<stdio.h>
#include<string.h>
int check_says()
{
      int a = 1;
 #include<stdio.h>
#include<string.h>
int check_says()
{
      int a = 1;
    //因为前面提到了大端字节和小端字节两个存储的方式不同,一个是最低的字节数据存在低地址,另一个低字节数据存放在高地址
    //我们只需要判断第一个字节如果拿出1为小端,不是1为大端
    //因为int占四个字节在内存中存储
    //char类型占用一个字节,强制转换为char*来访问它是否是大端还是小端
//    if(*(char*)&a==1)
//        return 1;
//    else
//        return 0;

//如果大端返回0,小端返回1
  return (*(char *)&a);//因为返回只有0/1,所以可以直接将代码简化
}
int main()
{
   if(check_says()==1)
       printf("小端");
   else
       printf("大端");
   //由此可见,数据在机器大部分是倒着存放的
    return 0;
}

2.练习题

signed char取值的范围是-128~127
unsgined char 取值的类型范围是0~255
如果存进去的值超出类型的范围,也会转换为其范围内的值
类型的作用:
1.申请内存空间时的大小
2.类型决定了看待内存中数据的视角 
#include<stdio.h>
int main()
{
    char a = -1;
    //10000000 00000000 00000000 00000001  -1原码
    //11111111 11111111 00000000 11111110  -1反码
    //11111111 11111111 00000000 11111111  -1补码
    //char类型只能存放8个bite位1个字节进行截断
    //11111111  a存放最低位数据
    //最高位位符号位,以原来的符号位提升
    //11111111 11111111 11111111 11111111 有符号整形提升高位补1  -补码a

    signed char b = -1;
    //11111111  b存放最低位数据的有效数字
    //11111111 11111111 11111111 11111111 高位补1  -补码b
    unsigned char c = -1;//unsigned 是个正数
    //11111111 c存放的值二进制数列也是它
    //无符号类型进行整形提升高位补0
    //00000000 00000000 00000000 11111111  //高位补0 -补码c
    //11111111 正数的原反补相同十进制为255
    printf("a=%d,b=%d,c=%d",a,b,c);
    //%d打印的是有符号的整数 
    //abc需要发生整形提升
    //-1 ,-1,255
    //%u打印的是无符号的整数
    return 0;
}

3.练习题

#include<stdio.h>
int main()
{
    char a = -128;
    // 10000000 00000000 00000000 100000000 原
    // 11111111 11111111 11111111 011111111 反码
    // 11111111 11111111 11111111 100000000 补码
    // 10000000 -a
    printf("%u\n", a);
    //%u打印的是无符号类型的数我们需要将a发生整形提升高位补1
    // 11111111 111111111 111111111 10000000
    //无符号的整数 原码反码 补码 相同的
    char b = 128;
    //char的最大类型范围为127
    //000000000 00000000 00000000 10000000 原反补相同
    //100000000 -b
    //111111111 11111111 11111111 11111111 补码
    //内存中的补码 %u认为存放的是无符号数,与a的结果相同
    printf("%u\n", b);
    return 0;
}

4.练习题

#include<stdio.h>
#include<string.h>
int main()
{
    char a[1000];//0~999
    int i;
    for (int i = 0; i < 1000;i++)
    {
        a[i] = -1 - i;//因为char是有符号类型走到-127之后为0
        //11111111+1后00000000,+1后char类型存储的值都被替换为0
        //因为char需要走到-128,然后不会在负,由正数127开始循环,直到0
    }
    //char类型取值范围为-128~127
    //char只能存8个bite位,11111111 正数没有符号位,都是有效位
    //如果char为signed char 负数为100000000 为-128
    //正数为01111111  为127

    printf("%zu", strlen(a));//strlen当遇到第一个0停止寻找,返回结果
    //127+128为255
    return 0;
}

练习5

#include<stdio.h>
#include<string.h>
unsigned char i = 0;//i的取值范围为0~255
int main()
{
    //循环判断的部分恒成立,会造成死循环
    for (int i = 0; i <= 255;i++)
    {
        printf("Hello world\n");
    }
        return 0;
}

练习题6

#include<stdio.h>
#include<unistd.h>
int main()
{
    unsigned int i;
    //无符号类型i>=0
    for (int i = 9; i>=0; i--)
    {
        printf("%d\n",i);
        sleep(1);
    }
    //9 8 7 6 5 4 3 2 1 0 -1在无符号整数中是一个很大的数字
        return 0;
}

练习题7

在这里插入图片描述

#include<stdio.h>
#include<unistd.h>
int main()
{
    int a[4] = {1, 2, 3, 4};
    int *ptr1 = (int*)(&a + 1);
    int* ptr2=(int*)((int)a+1);
    //a由int*类型转换为int类型+1整数+1赋给ptr2
    printf("%#x,%#x", ptr1[-1], *ptr2);
    //*ptr2访问四个int中的四个字节为0x02 00 00 00
    return 0;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值