25

我正在查看此页面: http: //www.devbistro.com/tech-interview-questions/Cplusplus.jsp,但不明白这个问题:

以下代码可能有什么问题?

long value;
//some stuff
value &= 0xFFFF;

注意:向候选人提示他们正在开发的基础平台。如果这个人仍然没有发现代码有任何问题,那么他们就没有使用 C++ 的经验。

有人可以详细说明吗?

谢谢!

4

7 回答 7

41

这里的几个答案表明,如果 anint的宽度为 16 位,0xFFFF则为负数。这不是真的。 0xFFFF永远不会是负面的。

十六进制文字由以下第一个足以包含它的类型表示: intunsigned intlongunsigned long

如果int宽度为 16 位,则0xFFFF大于 可表示的最大值int。因此,0xFFFFis 的类型unsigned int,保证足够大以表示0xFFFF

当执行通常的算术转换以评估 时&,将unsigned int转换为 a longunsigned int16 位到16 位的转换long是明确定义的,因为可以由 16 位表示的每个值unsigned int也可以由 32 位表示long

不需要符号扩展,因为初始类型没有符号,并且 using 的结果与 using0xFFFF的结果相同0xFFFFL

或者,如果int大于 16 位,则0xFFFF类型为int. 这是一个有符号但为正的数字。在这种情况下,两个操作数都是有符号的,并且long具有更大的转换等级,因此通过通常的算术转换int再次提升。long


正如其他人所说,您应该避免对有符号操作数执行按位运算,因为数字结果取决于符号的表示方式。

除此之外,这段代码没有什么特别的错误。我会争辩说,这是一个value在声明时未初始化的样式问题,但这可能是一个挑剔的级别注释,并且取决于//some stuff被省略的部分的内容。

使用固定宽度的整数类型(如uint32_t)可能更可取,而不是long为了更好的可移植性,但实际上这也取决于您正在编写的代码以及您的基本假设是什么。

于 2010-11-23T02:21:30.373 回答
3

我认为根据 long 的大小,可以将 0xffff 文字(-1)提升为更大的大小,并且作为有符号值,它将被符号扩展,可能成为 0xffffffff(仍然是 -1)。

于 2010-11-23T01:45:50.627 回答
2

我假设这是因为 long 没有预定义的大小,除了它必须至少与前面的大小 (int) 一样大。因此,根据大小,您可能会将值截断为位子集(如果 long 超过 32 位)或溢出(如果它小于 32 位)。

是的,多头(根据规范,感谢评论中的提醒)必须至少能够保持 -2147483647 到 2147483647(LONG_MIN 和 LONG_MAX)。

于 2010-11-23T01:40:19.847 回答
1

对于一个值在执行之前没有初始化,所以我认为行为是未定义的,值可以是任何东西。

于 2010-11-23T01:44:04.293 回答
0

long 类型大小是特定于平台/编译器的。

你可以在这里说的是:

  1. 它已签名。
  2. 我们无法知道 value &= 0xFFFF; 的结果;因为它可能是例如 value &= 0x0000FFFF; 并且不会做预期的事情。
于 2010-11-23T01:45:03.147 回答
0

虽然有人可能会争辩说,由于它不是缓冲区溢出或其他可能被利用的错误,它是一种风格而不是错误,但我有 99% 的信心认为问题作者正在寻找的答案是value在分配给它之前对其进行操作。该值将是任意垃圾,这不太可能是本意,因此“可能是错误的”。

于 2010-11-23T05:52:02.163 回答
-1

使用 MSVC,我认为该语句将执行最有可能的预期 - 即:清除除最不重要的 16 位值之外的所有值,但我遇到了其他平台,它们会将文字 0xffff 解释为等同于(短)-1,然后签署 extend 以转换为 long,在这种情况下,语句“value &= 0xFFFF”将无效。“value &= 0x0FFFF”更加明确和健壮。

于 2014-06-13T19:20:56.903 回答