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

开发者社区> shy丶gril> 正文

深入理解计算机系统-之-数值存储(二)--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; 
}

这里写图片描述


转载:http://blog.csdn.net/gatieme/article/details/50687118

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
数据中台的存储系统和计算平台枚举
采集&传输层 SqoopHadoop、关系型数据库之间传输数据的工具。传输时,会启动多个MR作业并发的传输数据 DataX阿里巴巴开源的数据同步工具,用来在各种异构数据源之间同步数据。
2323 0
C# String 前面不足位数补零的方法
在 C# 中可以对字符串使用 PadLeft 和 PadRight 进行轻松地补位。 PadLeft(int totalWidth, char paddingChar) //在字符串左边用 paddingChar 补足 totalWidth 长度 PadLeft(int totalWidth, char paddingChar) //在字符串右边用 paddingChar 补足
1490 0
深入理解计算机系统结构——虚拟存储器
虚拟存储器 虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。通过一个很清晰的机制,虚拟存储器提供了三个重要的能力: (1)它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存。
990 0
Python-技术篇-使用logging模块打印详细报错日志,获取报错信息位置行数方法
Python-技术篇-使用logging模块打印详细报错日志,获取报错信息位置行数方法
28 0
《逻辑与计算机设计基础(原书第5版)》——1.2 计算机系统设计的抽象层次
本节书摘来自华章计算机《逻辑与计算机设计基础(原书第5版)》一书中的第1章,第1.2节,作者:(美)M.莫里斯·马诺(M. Morris Mano)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1717 0
计算机中的层次化存储究竟是个什么鬼?
撸代码只是程序员的一项最基本的技能,除此之外,还有很多知识需要程序员掌握。【程序员进阶系列】专题,旨在分享程序员想要进一步提升自我,突破发展瓶颈的一系列技术。今天,我
19 0
+关注
1878
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载