计算机中的数字绝不是十进制格式。
问题不是它们什么时候变成二进制,而是什么时候变成十进制。
您应该能够获取二进制数 0b1111011 并将其转换为十进制的 123 和十六进制的 0x7B,而不是通过使用计算器上的基本转换按钮,而是通过了解从基本转换的工作原理,例如 3785 秒是 1 小时 3 分钟和5 秒(从 10 到 60)。
C 库看到你想要十进制,它需要位 0b1111011 在那一刻之前没有任何意义,它们只是位,在此之后它们将回到没有意义的计算机,至少对它们只有意义的计算机你。要得到 100 的位置,你必须除以 0b1100100,结果是 0b1,所以从 0b1111011 中减去 0b1100100,得到 0b10111,现在将其除以 0b1010,得到 0b10,所以从 0b10111 中减去 0b10100(0b1010 乘以 0b10),得到 0b11到目前为止,以 10 为底的转换是 0b1、0b10、0b11。现在 printf 需要从中生成 ASCII,因此它将 0b110000 添加到那些给出 0b110001、0b110010、0b110011 的数字上。并将该“字符串”输入字符输出例程(您会看到 123)。我们从来没有任何小数,它只是被操纵的位。
当你写一些代码时
unsigned int x = 5;
编译器将该 5(在源代码文件中实际上是 0b110101)转换为 0b101,并将其放置在决定存储变量 x 的任何位置。
现在让我们回到 0b1111011 并将其转换为十六进制,从右边开始,一次取 4 位,得到 0b111 和 0b1011,比迄今为止的基数 10 转换要快得多(通常,对于 8位号,如果这是它的话)。您可以添加 0b110000 然后与 0b111001 进行比较的两种方法之一,或者您可以与 0b1001 进行比较然后添加不同的数字。例如,0b111 变为 0b110111,然后检查它是否大于 0b111001,不,所以继续到 0b1011 添加 0b110000,你会得到 0b111011 是否大于 0b111001?是的,所以添加 0b111 或 0b100111 取决于您是想看到大写字母还是小写字母,现在字符串是例如 0b110111,0b1000010 加上终止零,您将其发送到打印并且您会在输出中看到 7B。
十六进制输出会更快是的。收益的多少和相关程度取决于许多因素...
现在我不知道你用十六进制编程源文件是什么意思
unsigned int x = 0x5;
编译时间会比
稍长
unsigned int x = 5;
因为多余的字符。但是
unsigned int x = 0x7B;
对
unsigned int x = 123;
嗯,十进制可能更快。
unsigned int x = 0x11111111;
对
unsigned int x = 286331153;
现在您不得不怀疑,在特定机器上,十六进制会更快,数据模式也很重要,如此处所示。
如此处所示,十六进制版本需要多两个字节的存储空间来保存源文件。
unsigned int x = 0x5;
unsigned int x = 5;
编译后的输出与应用于 x (0b101) 的常量相同。因此机器代码(和/或 .data 存储)不仅大小相同,而且相同。
unsigned int fun0 ( void )
{
return(5);
}
unsigned int fun1 ( void )
{
return(0x5);
}
unsigned int fun2 ( void )
{
return(123);
}
unsigned int fun3 ( void )
{
return(0x7B);
}
给出这个机器码
00000000 <fun0>:
0: e3a00005
4: e12fff1e
00000008 <fun1>:
8: e3a00005
c: e12fff1e
00000010 <fun2>:
10: e3a0007b
14: e12fff1e
00000018 <fun3>:
18: e3a0007b
1c: e12fff1e
已经存在并且现在存在带有 %b 的 C 库,但它是非标准的,从来没有意义为什么它不是。同样是八进制,嗯,八进制也有一个。
注意八进制转换与十六进制竞争,你没有条件
0b1111011,一次屏蔽和移出 3 位 0b001、0b111、0b011 添加 0x110000,就像您分别给出 0b110001、0b110111、0b110011 一样。所以你没有条件,但你有更多的“字符”要处理,对于 8 位数字,十六进制可以赢,但更大的八进制应该赢。
关于那个话题:
unsigned int fun0 ( void )
{
return(5);
}
unsigned int fun1 ( void )
{
return(0x5);
}
unsigned int fun2 ( void )
{
return(05);
}
unsigned int fun3 ( void )
{
return(123);
}
unsigned int fun4 ( void )
{
return(0x7B);
}
unsigned int fun5 ( void )
{
return(0173);
}
给予
00000000 <fun0>:
0: e3a00005
4: e12fff1e
00000008 <fun1>:
8: e3a00005
c: e12fff1e
00000010 <fun2>:
10: e3a00005
14: e12fff1e
00000018 <fun3>:
18: e3a0007b
1c: e12fff1e
00000020 <fun4>:
20: e3a0007b
24: e12fff1e
00000028 <fun5>:
28: e3a0007b
2c: e12fff1e
所以就源代码的“存储”而言,5 比 05 便宜,比 0x5 便宜,但 0x7B 与 0173 相同,但 123 更便宜。随着数字变大,十六进制变得最便宜(显然它具有更高的基数 16 vs 8 vs 10)。
您真的那么渴望源代码的存储空间吗?那么你需要成为一个标签人而不是一个太空人。并使用短变量名和函数名。我的长答案可能已经填满了你所有的内存。