为什么使用hex常量?

有时候我看到用hex定义的Integer常量,而不是十进制数字。 这是我从GL10课上拿的一小部分:

public static final int GL_STACK_UNDERFLOW = 0x0504; public static final int GL_OUT_OF_MEMORY = 0x0505; public static final int GL_EXP = 0x0800; public static final int GL_EXP2 = 0x0801; public static final int GL_FOG_DENSITY = 0x0B62; public static final int GL_FOG_START = 0x0B63; public static final int GL_FOG_END = 0x0B64; public static final int GL_FOG_MODE = 0x0B65; 

定义2914而不是0x0B62显然比较简单,那么可能会有一些性能增益? 我真的不这么认为,因为编译器的工作应该是改变它的。

这可能是组织和视觉清洁。 基数16与基数10的二进制关系要简单得多,因为在基数16中每个数字恰好对应于四位。

注意在上面,常数是用很多数字共同组成的。 如果它们用十进制表示,那么共同的位就不那么清楚了。 如果它们具有相同的十进制数字,则位模式不具有相同的相似度。

另外,在许多情况下,希望能够将按比例或常数一起创build标志的组合。 如果每个常量的值被限制为仅具有非零位的子集,则可以以可以被重新分离的方式来完成。 使用hex常量可以清除每个值中的哪些位是非零的。

还有其他两种合理的可能性:八进制或8进制简单地编码每个数字3位。 然后是二进制编码的十进制,其中每个数字需要四位,但是高于9的数字值被禁止 – 这将是不利的,因为它不能表示二进制可能的所有可能性。

“定义2914而不是0x0B62显然更简单”

我不知道这个具体情况,但通常情况并非如此。

在两个问题中:

  • A)什么是2914的位值?
  • B)0x0B62的位值是多less?

B会被很多开发者更快地回答。 (这也是类似的问题)


0x0B62(它是4位hex数字,所以它表示一个16位数字)

  • 0 = 0000的位
  • B = 1011的位
  • 6 = 0110的位
  • 2 = 0010的位

– >

0000101101100010

(我敢和2914一样。)


这是使用hex值的一个原因,另一个原因是值的来源可能使用hex(例如规范的标准)。

有时候我觉得它很愚蠢,比如:

 public static final int NUMBER_OF_TIMES_TO_ASK_FOR_CONFIRMATION = ...; 

用hex写几乎总是愚蠢的,我敢肯定,有些情况下不会。

例如,应用hex蒙版时的可读性。

在十进制数和hex数之间没有性能增益,因为代码将被编译为移动表示数字的字节常量。

电脑不做小数,他们(最好)二进制。 hex非常干净地映射到二进制,但它需要一些工作将十进制数转换为二进制。

一个hex闪烁的地方就是当你有一些相关的项目,其中很多是相似的,但是稍有不同。

 // These error flags tend to indicate that error flags probably // all start with 0x05.. public static final int GL_STACK_UNDERFLOW = 0x0504; public static final int GL_OUT_OF_MEMORY = 0x0505; // These EXP flags tend to indicate that EXP flags probably // all start with 0x08.. public static final int GL_EXP = 0x0800; public static final int GL_EXP2 = 0x0801; // These FOG flags tend to indicate that FOG flags probably // all start with 0x0B.., or maybe 0x0B^. public static final int GL_FOG_DENSITY = 0x0B62; public static final int GL_FOG_START = 0x0B63; public static final int GL_FOG_END = 0x0B64; public static final int GL_FOG_MODE = 0x0B65; 

用十进制数字,很难在大量不同但相关的项目中“注意”比特的恒定区域。

你宁愿写0xFFFFFFFF4294967295

第一个更清楚地表示了一个32位的数据types。 当然,很多经验丰富的程序员会认识到后者的模式,并且怀疑它的真实含义。 但即使在这种情况下,也更容易出现input错误等。

当涉及到大数字时,用hex表示它们使得它们更具可读性,因为它们更紧凑。

此外,有时转换为二进制也很重要:hex数字可以很容易地转换为二进制。 一些程序员喜欢这样做,这有助于在数字上进行位操作。

至于performance收益:不,没有。

hex是与二进制格式最接近的可读格式。 这例如简化了很多操作

0xB62等于2914 🙂

对于开发人员来说,当用hex表示的时候,比在以十进制表示时更容易思考一个常量的位模式。

这个事实使得以hex显示更适合API中使用的常量,其中比特和它们的位置(例如用作单独的标志)是相关的。

啊,但是0xDECAFF既是素数(1460959),又是紫色的颜色(在RGB中)。

对于颜色hex更加方便。

FF FF FF是白色00 00 FF是蓝色FF 00 00是红色00 FF 00是绿色很容易将颜色关系看作数字(虽然人眼的灰度和逼真度倾向于抛弃东西,但我们会忽略这些不便的物理事实纯粹mathamatical精度!

没有性能增益。

但是,如果这些常量与下面的某些位相对应,那么大多数程序员更喜欢hex(甚至二进制)来使其更清晰可读。

例如,可以很容易地看到GL_EXP2有2个位,1位和0x0800位(十进制为2048)。 十进制值2049将不太清楚。

有时使用位相关的algorithm更容易。 其他时候,它处理位比较,正如我在评论中的说法,4位(二进制数字)转换为1个hex字母,所以A3 = 10100011。

其他时候,这可能是有趣的或打破单调,虽然不熟悉hex的人可能会认为你正在做指针

 int data = 0xF00D; if ( val != 0xC0FFEE ) { data = 0xDECAF; } 

我有时用它来检查像int这样的东西的边界。 例如,你可以使用0x7FFFFFFF(0x80000000在很多情况下工作,但0x7F …更安全)来获得最大的int界限。 如果您没有像MAX_INT之类的语言,那么设置非常高的错误常量非常方便。 该技术也可以扩展,因为对于64位,可以使用0x7FFFFFFFFFFFFFFF。 您可能会注意到Android使用0x7_ __来进行R.id表查找。

我敢打赌,为了清楚起见,他们正在做这件事。 你可以很容易地使用整数,但如果你熟悉hex,这并不坏。 看起来他们正在为某些函数保留x值。 在十进制中,你会做一些像0-99是错误,100-199其他的东西,等等。 他们如何做这个比例是不同的。

在性能方面,由于编译器(即使是很多汇编程序)最终将任何格式转换为二进制,无论是十进制,八进制,hex,浮点数还是双精度等等,您都不会在运行时获得任何好处。