在编写一些面试测试题时,我目前正在从各种来源中抽取例子并通过它们来衡量他们的难度和正确性。我遇到了一个我认为已经破碎的东西,但也有可能我错过了一些东西:如果我,我想知道,不仅仅是因为我自己的知识,但它也会表明这可能是一个好的,棘手的问题。我希望你能帮我恢复理智,并重新肯定我对自己的信任。 :d
在占位符处投射p的正确方法是什么?#34; ???"在以下代码中?
#include <iostream> using namespace std; uint16_t hash(void *p) { uint32_t val = ???; return (uint16_t)(val ^ (val >> 16)); } int main(int argc, char *argv[]) { uint32_t a[20]; for(uint32_t i = 0; i < 20; ++i) { a[i] = i; cout << hash(a + i) << endl; } }
选择一个:
static_cast<uint32_t>(p)
dynamic_cast<uint32_t>(p)
reinterpret_cast<uint32_t>(p)
const_cast<uint32_t>(p)
暂时忽略对hash
的调用必须::hash
以保证与标准库的歧义(例如,此行在GCC 5.3.0中不为我编译,C + +14模式),我对这个问题有疑问。
首先,它不清楚该计划应该做什么。散列数组值,还是散列元素位置?因为此时函数正在接收指向元素的指针,但所有可用的答案都假定这些指针本身将转换为uint32_t
并用作哈希值。如果是这种情况,那么即使您使用reinterpret_cast
,然后使用there is a bug because sizeof(void*)
may not be sizeof(uint32_t)
; val
in that function should be intptr_t
instead。使用uint32_t
作为数组元素本身的类型只会使事情进一步混淆,如果它实际上是共同发生的。
或者该函数应该对值进行散列,并且正确答案不在列表中:*static_cast<uint32_t*>(p)
。
&#34;正确&#34;答案显然是reinterpret_cast<uint32_t>(p)
,这让我觉得程序的意图是散列数组元素地址。
我想象这些问题吗?
问题是否清晰,解决方案是提供的四种选择之一?
答案 0 :(得分:5)
总结一下您在问题和评论中提出的所有观点。基本上,这个问题的答案可能是:
使用的正确演员是
reinterpret_cast
1 † ‡。功能
这是很多脚注!我想这就是真正的C ++问题。在任何情况下,我都不会在面试中提出这个问题 - 这是一个太过戏法的问题 - 而且你可以提出真实,直接的答案,而且还有很多真正的问题。
1 在64位系统上,您不能将void*
任意_kind_of_cast转换为uint32_t
。所以他们都错了。
†在用户提供的hash()
和类模板std::hash<T>
之间,C ++ 11中存在名称查找问题。您显然应将它们与why is using namespace std;
considered bad practice?
‡即使上面没有阻止代码编译的问题,这里的意图是将指针实际哈希到a
而不是a
的值?最可能正确的答案应该是:
auto val = *static_cast<const uint32_t*>(p);
如果 关于散列指针,那么reinterpret_cast
将是正确的演员,但不到uint32_t
(如(1)所示) 。我们希望使用uintptr_t
:
auto val = reinterpret_cast<uintptr_t>(p);
在64位的情况下,你可能想要做一些比val ^ (val >> 16)
更多的事情,因为你有效地忽略了高32位,但至少这会让你感到高兴一个可以在任何地方编译的正确演员。
答案 1 :(得分:4)
恕我直言,你在想象这些问题:) 这个例子来自这里:reinterpret_cast 因此,最好在该文章的上下文中查看示例。
问题很清楚,但是当我读完所有评论后,我开始怀疑我的第一分钟使用reinterpret_cast的解决方案(即使没有上下文,我也会用它作为答案)