我正在查看此页面: http: //www.devbistro.com/tech-interview-questions/Cplusplus.jsp,但不明白这个问题:
以下代码可能有什么问题?
long value; //some stuff value &= 0xFFFF;
注意:向候选人提示他们正在开发的基础平台。如果这个人仍然没有发现代码有任何问题,那么他们就没有使用 C++ 的经验。
有人可以详细说明吗?
谢谢!
我正在查看此页面: http: //www.devbistro.com/tech-interview-questions/Cplusplus.jsp,但不明白这个问题:
以下代码可能有什么问题?
long value; //some stuff value &= 0xFFFF;
注意:向候选人提示他们正在开发的基础平台。如果这个人仍然没有发现代码有任何问题,那么他们就没有使用 C++ 的经验。
有人可以详细说明吗?
谢谢!
这里的几个答案表明,如果 anint
的宽度为 16 位,0xFFFF
则为负数。这不是真的。 0xFFFF
永远不会是负面的。
十六进制文字由以下第一个足以包含它的类型表示: int
、unsigned int
、long
和unsigned long
。
如果int
宽度为 16 位,则0xFFFF
大于 可表示的最大值int
。因此,0xFFFF
is 的类型unsigned int
,保证足够大以表示0xFFFF
。
当执行通常的算术转换以评估 时&
,将unsigned int
转换为 a long
。unsigned int
16 位到16 位的转换long
是明确定义的,因为可以由 16 位表示的每个值unsigned int
也可以由 32 位表示long
。
不需要符号扩展,因为初始类型没有符号,并且 using 的结果与 using0xFFFF
的结果相同0xFFFFL
。
或者,如果int
大于 16 位,则0xFFFF
类型为int
. 这是一个有符号但为正的数字。在这种情况下,两个操作数都是有符号的,并且long
具有更大的转换等级,因此通过通常的算术转换int
再次提升。long
正如其他人所说,您应该避免对有符号操作数执行按位运算,因为数字结果取决于符号的表示方式。
除此之外,这段代码没有什么特别的错误。我会争辩说,这是一个value
在声明时未初始化的样式问题,但这可能是一个挑剔的级别注释,并且取决于//some stuff
被省略的部分的内容。
使用固定宽度的整数类型(如uint32_t
)可能更可取,而不是long
为了更好的可移植性,但实际上这也取决于您正在编写的代码以及您的基本假设是什么。
我认为根据 long 的大小,可以将 0xffff 文字(-1)提升为更大的大小,并且作为有符号值,它将被符号扩展,可能成为 0xffffffff(仍然是 -1)。
我假设这是因为 long 没有预定义的大小,除了它必须至少与前面的大小 (int) 一样大。因此,根据大小,您可能会将值截断为位子集(如果 long 超过 32 位)或溢出(如果它小于 32 位)。
是的,多头(根据规范,感谢评论中的提醒)必须至少能够保持 -2147483647 到 2147483647(LONG_MIN 和 LONG_MAX)。
对于一个值在执行之前没有初始化,所以我认为行为是未定义的,值可以是任何东西。
long 类型大小是特定于平台/编译器的。
你可以在这里说的是:
虽然有人可能会争辩说,由于它不是缓冲区溢出或其他可能被利用的错误,它是一种风格而不是错误,但我有 99% 的信心认为问题作者正在寻找的答案是value
在分配给它之前对其进行操作。该值将是任意垃圾,这不太可能是本意,因此“可能是错误的”。
使用 MSVC,我认为该语句将执行最有可能的预期 - 即:清除除最不重要的 16 位值之外的所有值,但我遇到了其他平台,它们会将文字 0xffff 解释为等同于(短)-1,然后签署 extend 以转换为 long,在这种情况下,语句“value &= 0xFFFF”将无效。“value &= 0x0FFFF”更加明确和健壮。