如何将变量中的值以二进制形式打印出来
先看源码:
#include <stdio.h>
#include <string.h>
const char *uint64_to_binary(int n)
{
static char str[33];
str[0] = '\0';
for (unsigned i = 0xffffffff / 2 + 1; i > 0; i >>= 1) {
strcat(str, ((n & i) == i) ? "1" : "0");
}
return str;
}
int main()
{
printf("%s\n", uint64_to_binary(1));
return 0;
}
要打印出每个位的核心思想就是一个位一个位的去比较,如何该位为 1 就记录为 “1”,如果该位为 0 就记录为 “0”,比较一次记录一次。最后输出字符串中的结果。
0xffffffff / 2 + 1
就是将内存中最高位置为 1 其他位置为 0。如果电脑是小端处理器(数据低字节保存在内存的低地址中),那么内存中存储的应该就是 10000000 00000000 00000000 00000000
,每一次循环就把该数右移一位,内存上体现的就是 1 在一格一格的向右移动。假如我们要输出的数它在内存中实际存储是这个样子 00000000 00000000 00000000 11111111
。
第 1 次循环:10000000 00000000 00000000 00000000
& 00000000 00000000 00000000 11111111
= 00000000 00000000 00000000 00000000
所以 str = “0”。
第 2 次循环:01000000 00000000 00000000 00000000
& 00000000 00000000 00000000 11111111
= 00000000 00000000 00000000 00000000
所以 str = “00”
……
第 25 次循环:00000000 00000000 00000000 10000000
& 00000000 00000000 00000000 11111111
= 00000000 00000000 00000000 00000000
所以 str = “0000000000000000000000001”
……
这样就把内存中每个位的值打印出来了。如果要打印的是 1 个字节的变量,就得将 0xffffffff
修改成 0xff
。
引申
打印变量在内存的每个位是直观了解其在内存分布的方式,其实了解一个变量在内存中是怎么存储的,有利于我们解决异构 CPU 跨字节交互数据的问题。比如一台英特尔 CPU 的电脑(小端处理器)往一个 ESP32(大端处理器)上发送一个 4 字节的整型变量。电脑将 unsigned int a = 255
, 内存中的数据(0x000000ff
)直接发到 ESP32 上,ESP32 收到数据后直接内存拷贝到ESP32 中的 unsigned int b
变量上,则 b 的数值就为 4278190080
,这样就很有可能造成程序运行错误。特别是这种跨平台跨字节交互数据的情况应该特别小心,做个大小端转换就没事了。说的容易,但是理解数据在内存中实际的存储情况才是关键。