为什么要使用十六进制常量?

时间:2012-06-06 18:59:46

标签: java opengl decimal hex

有时我会看到以十六进制定义的整数常量,而不是十进制数。这是我从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显然更简单,那么可能会有一些性能提升吗?我一点也不这么认为,从那以后改编它应该是编译器的工作。

11 个答案:

答案 0 :(得分:61)

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

注意上面的常量如何将常量分组为多个数字。如果它们以十进制表示,则共同的位将不太清楚。如果它们具有共同的十进制数字,则位模式将不具有相同的相似度。

此外,在许多情况下,希望能够一起按位OR运算以创建标志组合。如果每个常量的值被约束为仅具有非零的位的子集,则可以以可以重新分离的方式来完成。使用十六进制常量可以清楚地表明每个值中的哪些位非零。

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

答案 1 :(得分:25)

“定义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 = ...;

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

答案 2 :(得分:9)

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

答案 3 :(得分:8)

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

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

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

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

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

答案 4 :(得分:6)

您是想写0xFFFFFFFF还是4294967295

第一个更清楚地表示具有全部的32位数据类型。当然,许多经验丰富的程序员会认识到后一种模式,并且怀疑其真正的含义。但即使在这种情况下,它也更容易出现输入错误等。

答案 5 :(得分:5)

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

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

至于表现收益:不,没有。

答案 6 :(得分:3)

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

答案 7 :(得分:3)

0xB62等于2914 :-)

对于开发人员来说,当用十六进制表示常量的位模式比将其表示为基数为10的整数时,更容易对其进行精神描绘。

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

答案 8 :(得分:3)

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

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

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

答案 9 :(得分:2)

没有性能提升。

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

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

答案 10 :(得分:1)

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

其他时候,它既有趣又打破单调,但不熟悉十六进制的人可能会认为你是用指针做事

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

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

我打赌他们是为了清晰起见而这样做的。你可以很容易地使用整数,但如果你熟悉十六进制,那就不错了。看起来他们正在为某些功能保留x值。在十进制中,你会做一些像0-99这样的错误,100-199用于别的东西,等等。他们如何做到这一点的方式不同。

在性能方面,你在运行时什么也得不到,因为编译器(甚至很多汇编器)最终将任何格式转换为二进制,无论是十进制,八进制,十六进制,浮点数,双精度等等。