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

时间:2023-01-11 17:40:17

大端与小端


前面我们提到了依据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;
}

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

打印变量的的每一个位


算法分析


前面通过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;
}

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