您的位置:首页 > 理论基础

深入理解计算机系统-之-数值存储(四)--整数在内存中的存储方式

2016-02-21 16:04 483 查看

前景回顾

前面我们了解到依据CPU的端模式的架构不同,数据的存储的字节序也不同

BE big-endian 大端模式,最直观的字节序 地址低位存储值的高位,地址高位存储值的低位 ,数据填写时,不要考虑对应关系,只需要把内存地址从左到右按照由低到高的顺序写出,把值按照通常的高位到低位的顺序写出,两者对照,一个字节一个字节的填充进去。

LE little-endian 小端模式,则最符合人的思维的字节序,地址低位存储值的低位,地址高位存储值的高位 ,这点比较符合人的思维的字节序,是因为从人的第一观感来说,低位值小,就应该放在内存地址小的地方,也即内存地址低位,反之,高位值就应该放在内存地址大的地方,也即内存地址高位

任何数据在内存中都是以二进制的形式存储的。

具体参照深入理解计算机系统-之-数值存储(一)-CPU大端和小端模式详解

接着我们讨论了如何通过程序打印出变量在内存中的存储形式,具体参照深入理解计算机系统-之-数值存储(二)–C程序打印变量的每一字节或者位

然后我们了解了原码,反码,补码和移码的表示形式,具体参照深入理解计算机系统-之-数值存储(三)– 原码、反码、补码和移码详解

示例程序

那现在我们明细了。我们通过下面的程序来查看,整数在内存中的表现形式。

[code]#include <stdio.h>
#include <stdlib.h>

int check_end()
{
    int   i = 0x12345678;
    char *c = (char *)&i; 

    return (*c == 0x12);
}

int print_bit(void *addr, int size)
{

    unsigned char *ptr = (unsigned char *)addr;
    int print_bytes = 0;

    if(ptr == NULL)
    {
        return -1; 
    }

    for(print_bytes = 0;
        print_bytes < size;
        print_bytes++, ptr++)
    {
#ifdef DEBUG
        printf("byte %d, data = %02x -=>", print_bytes, *ptr); 
#endif
        for(int print_bits = 7;
        print_bits >= 0;
        print_bits--)
        {
            printf("%d", ((*ptr >> print_bits) & 1));
        }
#ifdef DEBUG
        printf("\n");
#endif

    }
    printf("\n"); 

    return print_bytes;
}

int print_byte(void *addr, int size)
{
    unsigned char *paddr = (unsigned char *)addr;
    int print_bytes = 0;

    if(paddr == NULL)
    {
        return -1; 
    }

    while(print_bytes < size)
    {
        printf("%02x", *paddr); 
        paddr++; 
        print_bytes++; 
    }
    printf("\n"); 
    return print_bytes; 
}

int main(void)
{
    if(check_end() == 1)
    {
        printf("大端模式\n");
    }
    else
    {
        printf("小端模式\n");
    }

    int a = 1;
    print_bit((void *)&a, sizeof(a));

    int b = -1;
    print_bit((void *)&b, sizeof(b));

/*
X   = -00101011 = 0x0000002B 
[X]原= 10000000 00000000 00000000 00101011
[X]反= 11111111 11111111 11111111 11010100
[X]补= 11111111 11111111 11111111 11010101
[X]移=01010101
*/

    int x = 0x2B;
    print_bit((void *)&x, sizeof(x));
    int y = -0x2B;
    print_bit((void *)&y, sizeof(y));

    return EXIT_SUCCESS;
}


程序分析




不管是原码,反码还是,补码,正数的表示方法是一致的。

但是负数来说,是有区别的。

X = -0X2B = -00101011 = 0x0000002B

[X]原 = 10000000 00000000 00000000 00101011 = 0x8000002B

[X]反 = 11111111 11111111 11111111 11010100 = 0xFFFFFFD4

[X]补 = 11111111 11111111 11111111 11010101 = 0xFFFFFFD5

[X]移 =01010101

由于我们的intel的CPU架构采用小端模式,那么用补码存储的时候,0xFFFFFFD5用小端模式存储下来,低字节到高字节的数据排列下来依次是0x D5 FF FF FF,即11010101 11111111 11111111 11111111
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: