64

有时我会看到以十六进制而不是十进制数字定义的整数常量。这是我从 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;

它显然比定义更简单29140x0B62所以可能会有一些性能提升吗?我真的不这么认为,从那时起改变它应该是编译器的工作。

4

11 回答 11

72

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

请注意,在上面,常量是如何与许多共同的数字分组的。如果它们用十进制表示,共同的位就不太清楚了。如果它们具有相同的十进制数字,则位模式将不会具有相同程度的相似性。

此外,在许多情况下,希望能够将常量按位或一起创建标志组合。如果每个常数的值被限制为只有一个非零位的子集,那么这可以通过一种可以重新分离的方式来完成。使用十六进制常量可以清楚地知道每个值中哪些位是非零的。

还有另外两种合理的可能性:八进制或以 8 为基数仅对每个数字 3 位进行编码。然后是二进制编码的十进制,其中每个数字需要四位,但禁止超过 9 的数字值 - 这将是不利的,因为它不能代表二进制可以代表的所有可能性。

于 2012-06-06T19:07:41.467 回答
27

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

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

出了这两个问题:

  • A) 2914 的位值是多少?
  • B) 0x0B62 的位值是多少?

很多开发者会更快更正确地回答 B。(这也适用于类似的问题)


0x0B62(它是 4 个十六进制数字长,因此它表示一个 16 位数字)

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

->

0000101101100010

(我敢让你对 2914 做同样的事情。)


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

有时我只是觉得它很愚蠢,例如:

public static final int NUMBER_OF_TIMES_TO_ASK_FOR_CONFIRMATION = ...;

用十六进制写几乎总是很愚蠢,我敢肯定在某些情况下它不会。

于 2012-06-06T19:09:23.263 回答
10

例如,应用十六进制掩码时的可读性。

于 2012-06-06T19:03:15.260 回答
9

十进制数和十六进制数之间不会有性能提升,因为将编译代码以移动表示数字的字节常量。

计算机不做十进制,它们(充其量)做二进制。十六进制映射到二进制非常干净,但是将十进制数转换为二进制需要一些工作。

十六进制发光的一个地方是当你有许多相关的项目时,其中许多相似,但略有不同。

// 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;

对于十进制数,人们很难“注意到”大量不同但相关的项目中的恒定位区域。

于 2012-06-06T19:04:03.860 回答
6

当涉及到大数字时,以十六进制表示它们会使它们更具可读性,因为它们更紧凑。

此外,有时转换为二进制也很重要:十六进制数可以很容易地转换为二进制。一些程序员喜欢这样做,这有助于对数字进行位运算。

至于性能增益:不,没有。

于 2012-06-06T19:04:44.003 回答
6

你宁愿写0xFFFFFFFF还是4294967295

第一个更清楚地表示全为 1 的 32 位数据类型。当然,许多经验丰富的程序员会认出后一种模式,并暗中怀疑它的真正含义。但是,即使在这种情况下,它也更容易出现打字错误等。

于 2012-06-06T19:59:33.323 回答
3

十六进制是最接近二进制格式的可读格式。这简化了很多位操作,例如

于 2012-06-06T19:04:25.193 回答
3

0xB62 等于 2914 :-)

对于开发人员来说,以十六进制表示的常量比以 10 为基数的整数表示时更容易在脑海中描绘常量的位模式。

这一事实使得十六进制表示更适合 API 中使用的常量,其中位及其位置(例如用作单独的标志)是相关的。

于 2012-06-06T19:05:28.763 回答
3

啊,但是 0xDECAFF 既是素数(1460959),又是一种令人愉悦的紫色(RGB)。

对于颜色十六进制更方便。

FF FF FF 是白色 00 00 FF 是蓝色 FF 00 00 是红色 00 FF 00 是绿色 很容易将颜色关系视为数字(虽然人眼的伽马和保真度往往会丢掉东西,但我们会忽略为了纯粹的数学精度,那些不方便的物理事实!

于 2013-06-14T21:17:45.373 回答
2

没有性能增益。

但是,如果这些常量对应于下面的某些位,则大多数程序员更喜欢十六进制(甚至二进制)以使其清晰易读。

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

于 2012-06-06T19:03:55.957 回答
2

有时使用与位相关的算法会更容易。其他时候,它处理位比较,正如我在评论中的陈述,4 位(二进制数字)转换为 1 个十六进制字母,因此,A3 = 10100011。

其他时候,它要么很有趣,要么打破单调,尽管不熟悉 hex 的人可能会认为你是在用指针做事

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

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

我敢打赌,他们这样做是为了清楚起见。您可以轻松地使用整数,但如果您熟悉十六进制,那也不错。看起来他们正在为某些函数保留 x 值。在十进制中,你会做类似 0-99 是错误的事情,100-199 是其他的事情,等等。他们如何做到这一点是不同的。

性能方面,您在运行时一无所获,因为编译器(甚至很多汇编程序)最终会将任何格式转换为二进制,无论是十进制、八进制、十六进制、浮点、双精度等。

于 2013-01-03T15:13:41.120 回答