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