29.数据的存储

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
    int i = 0;
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
                                             //   Debug的地址     Release的地址
    printf("%p\n", &i);             //    0018FA50            001CFEF0
    printf("%p\n", &arr[9]);     //    0018FA44            001CFF18

    //for (i = 0;i <= 12;i++)
    //{
    //    arr[i] = 0;
    //    printf("hehe\n");        //死循环
    //}
    return 0;
}
解释:
i和arr是局部的变量
因为局部变量是放在栈区上的
并且栈区的使用习惯是:先使用高地址,再使用低地址
数组随着下标的增长,地址是由低到高变化的
i的地址就再arr的地址后面两个,然后i就变成0了。

但是Release没有死循环  所以Release版本是做过优化的

1.数据的分类
整形家族
浮点型家族
构造类型 - 自定义类型
 {
    struct 结构体类型
  数组
  枚举
    联合体
 }
指针类型
     
空类型
 {
    void 
        {    
        函数返回类型 void test();
        函数参数     void test(void);
        指针         void* p;
        }
 }
int main()             //数组是自定义的
{
    int arr[10];        //int[10]
    int arr2[5];        //int [5]

    return 0;
}

2.整形在内存中的存储
int main()
{
    int a = -10;
    //
    //10000000000000000000000000001010-原码
    //11111111111111111111111111110101-反码
    //11111111111111111111111111110110-补码
    //FFFFFFF6

    return 0;
}

数据在内存中以2进制
对于整数来说:
整数二进制有3种表示形式:原码,反码,补码
正整数:原码,反码,补码相同
负整数:原码,反码,补码要进行计算
按照数据的数值直接写出的二进制序列就是原码
原码的符号位不变,其它位按位取反,得到的就是反码
反码+1,得到的就是补码
当 反码 -> 补码 可以倒回去算 或者 再次取反+1

整数在内存中存储的是补码


为什么不存原码存反码呢?
使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理

1 - 1;             //CPU是不能使用减法的,所以用加法来运算
1 + (-1);
    
用原码来计算:
00000000000000000000000000000001
10000000000000000000000000000001
10000000000000000000000000000010
-2
用补码来计算:
00000000000000000000000000000001 - 1的补码
11111111111111111111111111111111 - (-1)的补码
00000000000000000000000000000000
0

int main()
{
    int a = -10;
    int b = 10;
    //b的数据是:
    //二进制:   10000000000000000000000000001010
    //16进制:   00 00 00 0a
    //VS存储: 0a 00 00 00

    return 0;
}
依上面的可以看出,计算机的存储是靠其他方法的
具体方法就是 : 大端字节序和小端字节序
大端字节序:把数据的低位字序的内容存放在 高 地址处,高位字节序的内容存放在 低 地址处 
小端字节序:把数据的低位字序的内容存放 在 低 地址处,高位字节序的内容存放在 高 地址处 - VS采用的
int main()
{
    int a = 0x11223344;  //11 22 33 44 - 大端字节序  ;  44 33 22 11 - 小端字节序
    return 0;                    //把数据的低位字序的内容存放在高位地址处,高位字节序的内容存放放在低位处
}

百度2015年系统工程师笔试题
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序
把数据低位字节序的内容放在高地址处,高位的内容放在低地址处是大端字节序
int main()
{
    //写代码判断字节序
    int a = 1;
    char* p = (char*)&a;
    if (*p = 1)
    {
        printf("小端");
    }
    else
    {
        printf("大端");

    }
    return 0;
}

输出什么?
int main()
{
    char a = -1;
    100000000000000000000000000000000001
    111111111111111111111111111111111110
    111111111111111111111111111111111111
    11111111
    111111111111111111111111111111111111-补码,打印原码
    signed char b = -1;
    11111111
    unsigned char c = -1; 
    11111111
    000000000000000000000000000011111111 - 原码 - 255
    printf("a=%d,b=%d,c=%d", a, b, c);
    return 0;
}

补充:
1.char 到底是signed char 还是 unsigned char ?
C语言标准并没有规定,取决于编译器
int 是 signed int   ;   short 是 signed short

输出什么?
int main()
{
    char a = -128;//1000 0000
    10000000000000000000000010000000
    11111111111111111111111101111111
    11111111111111111111111110000000-补码
    10000000
    11111111111111111111111110000000-整形提升
    因为用的是%u打印的,高位就不是符号位,补码就是原码

    printf("%u\n",a);         // 4294967168
    return 0;
}

结果?
int main()
{
    char a = 128;
    printf("%u\n", a);
    00000000000000000000000010000000 - 原反补相同
    00000000
    11111111111111111111111110000000

    return 0;
}

补充:
char类型变量的取值范围:
有符号char的取值范围是:[-128,127] 

int main()
{
    int i = -20;
    unsigned int j = 10;
    10000000000000000000000000010100
    11111111111111111111111111101011
    11111111111111111111111111101100
                  +
    00000000000000000000000000001010
                  =
    11111111111111111111111111110110-补码
    11111111111111111111111111110101
    00000000000000000000000000001010-原码-10
    printf("%d\n", i + j);        //-10
    //i+j是大于0的,因为j是无符号整形,算出的结果也是个无符号数,单看结果是大于0的
    //以%d的形式打印,内存是存补码,要转成原码,所以打印出来的才是个负数
    return 0;
}

int main()
{
    unsigned int i;
    for (i = 9;i >= 0;i--)
    {
        printf("%u\n", i); //死循环
        //即使i是unsigned,但是用%d打印的话,它还是按有符号的打印
    }

    return 0;
}

int main()
{
    char a[1000];
    int i;
    for (i = 0;i < 1000;i++)
    {
        a[i] = -1 - i;
    }
    //-1 -2 -3 .. -127 -128 127 126 125 ... 3 2 1 0 -1 -2 -3 .. 
    printf("%d", strlen(a));//找到\0
    return 0;
}

unsigned char i = 0;
int main()
{
    for (i = 0;i <= 255;i++);
    {
        printf("hello world\n");        //死循环
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值