深入理解计算机系统-之-数值存储(二)--C程序打印变量的每一字节或者位

大端与小端


前面我们提到了依据CPU端模式的不同,数据的存储顺序也不一样。

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

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

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

打印变量的的每一个字节


算法分析


但是理论我们已经讲的很详细了,却没有真正看过数据的存储结果,因此我们期待能够利用C语言编写程序输出变量的的每一位

思路:

C语言中char 必须对应一个byte , 所以它的类型固定是1个字节。

用一个char*的指针指向变量的首地址,往后顺序读取sizeof个字节的数据,就可以访问到变量的每一位

/*
addr  -=> 待打印的变量的首地址 
size  -=>·待打印的变量的大小 
return 成功返回打印的字节数  
*/
int print_all_byte(void *addr, int size)
{
    unsigned char *ptr = (unsigned char *)addr;
    int print_bytes = 0;

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

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

示例程序


首先我们判断一下当前电脑的大小端模式,然后分别定义了short,int,long,float,double,array数组几种类型的数据。
然后分别打印了它的每一个字节的信息。

#include <stdio.h>
#include <stdlib.h>


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

    return (*c == 0x12);
}


int CheckEnd()
{
    union
    {
        int a;
        char b;
    }u;

    u.a = 1;
    if (u.b == 1)
        return 0;
    else 
        return 1;
}

/*
addr  -=> 待打印的变量的首地址 
size  -=>·待打印的变量的大小 
return 成功返回打印的字节数  
*/
int print_all_byte(void *addr, int size)
{
    unsigned char *ptr = (unsigned char *)addr;
    int print_bytes = 0;

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

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

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

    short shortvalue = 0x1234; 
    if(print_all_byte((void *)&shortvalue, sizeof(shortvalue)) != -1)
    {
        printf("print SHORT success!\n\n"); 
    }

    int intvalue = 0x12345678; 
    if(print_all_byte((void *)&intvalue, sizeof(intvalue)) != -1)
    {
        printf("print INT success!\n\n"); 
    }

    long longvalue = 0x87654321; 
    if(print_all_byte((void *)&longvalue, sizeof(longvalue)) != -1)
    {
        printf("print LONG success!\n\n"); 
    }

    float floatvalue = 0.12345678; 
    if(print_all_byte((void *)&floatvalue, sizeof(floatvalue)) != -1)
    {
        printf("printf FLOAT success!\n\n"); 
    }

    double doublevalue = 0.12345678; 
    if(print_all_byte((void *)&doublevalue, sizeof(doublevalue)) != -1)
    {
        printf("printf DOUBLE success!\n\n"); 
    }

    int array[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 1234}; 
    if(print_all_byte((void *)array, sizeof(array)) != -1)
    {
        printf("printf ARRAY success!\n\n"); 
    }


    return EXIT_SUCCESS; 
}

这里写图片描述

打印变量的的每一个位


算法分析


前面通过char我们可以读取到变量的每个字节,我们进一步拓展,读取每一个字节后,再取出其对应的每一位,即可按照二进制的方式输出每个位。
读取每一位的操作,即判断某一位是1还是0,可以采用位运算完成,具体操作如下。

int isset(char data, int bit)
{ 
    data >>= bit;

    if(data & 1 == 0) 
    {
        return 0; 
    }
    else
    {
        return 1; 
    }
}

所以我们对上面的算法进行拓展,先取到每一个byte,然后再读取该byte的每一个bit。

int print_bit(char *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++)
    {
        for(int print_bits = 7;
        print_bits >= 0;
        print_bits--)
        {
            printf("%d", ((*ptr >> print_bits) & 1));
        }

    }
    printf("\n"); 
    return print_bytes;
}

示例程序


#include <stdio.h>
#include <stdlib.h>


//#define DEBUG
int isset(char data, int bit)
{ 
    data >>= bit;

    if(data & 1 == 0) 
    {
        return 0; 
    }
    else
    {
        return 1; 
    }
}

/*
addr  -=> 待打印的变量的首地址 
size  -=>·待打印的变量的大小 
return 成功返回打印的字节数  
*/
int print_bit(char *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"); 
}

int main(void)
{
    /*short shortvalue = 0x1234; 
    if(print_bit((char *)&shortvalue, sizeof(shortvalue)) != -1)
    {
        printf("print SHORT success!\n\n"); 
    }*/

    int intvalue = 0x12345678;
    if(print_bit((char *)&intvalue, sizeof(intvalue)) != -1)
    {
        printf("print INT success!\n\n"); 
    }

    long longvalue = 0x87654321; 
    if(print_bit((char *)&longvalue, sizeof(longvalue)) != -1)
    {
        printf("print LONG success!\n\n"); 
    }

    float floatvalue = 0.12345678; 
    if(print_bit((char *)&floatvalue, sizeof(floatvalue)) != -1)
    {
        printf("printf FLOAT success!\n\n"); 
    }

    double doublevalue = 0.12345678; 
    if(print_bit((char *)&doublevalue, sizeof(doublevalue)) != -1)
    {
        printf("printf DOUBLE success!\n\n"); 
    }

    int array[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 1234}; 
    if(print_bit((char *)array, sizeof(array)) != -1)
    {
        printf("printf ARRAY success!\n\n"); 
    }


    return EXIT_SUCCESS; 
}

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值