2016-02-19 50 views
6

在编写一些面试测试题时,我正在通过各种来源的例子,并通过它们来测试他们的难度和正确性。我遇到了一个我认为已经坏了的东西,但也有可能我错过了一些东西:如果我是,我想知道,不仅仅是为了我自己的知识,但是它也表明这可能是一个好的,棘手的问题。我希望你能帮助我重新获得理智并重申我对自己的信任。 :D据我所知,这些答案都不正确。我错过了什么?

什么是在占位符“???”上投P的正确方法是什么?在下面的代码中?

#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)

“正确”的答案显然是reinterpret_cast<uint32_t>(p),这让我觉得程序的意图是散列数组元素地址。

我在想像这些问题吗?
问题是否清晰并且解决方案是提供的四种选择之一?

+0

不能真正发布这个答案,但对我来说,它看起来好像你的分析是正确的,面试问题是错误的,除非我在这里失去了一些至关重要的东西。 – Cubic

+2

你为什么要散列任意指针?这有什么用途?我认为你假设它采用'* x_cast (p)'的形式是正确的。 – tadman

+0

我不认为这个问题是可以回答的;只有编写代码的人知道它的意图。他可能打算散列地址值,或散列元素本身。 –

回答

5

只是要总结您在问题和评论中提出的所有观点。基本上,这个问题的答案可能是:

正确的投用为reinterpret_cast&匕首;&Dagger;

这是很多脚注!我想这就是它真正的C++问题。无论如何,我不会在面试中提出这个问题 - 这太诡异的问题 - 而且真正的问题有很多,你可以提出真正的,直接的答案。


在64位系统上,无法any_kind_of_cast一个void*uint32_t。所以他们都错了。

&dagger;在用户提供的hash()和类模板std::hash<T>之间,C++ 11中存在名称查找问题。你应该明显地将它们链接到why is using namespace std; considered bad practice?

&Dagger;即使上述问题不是阻止代码首先编译的问题,这里的意图是实际上将指针散列为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位,但至少这会让你得到一个能在任何地方编译的正确角色。

+2

嗯,我觉得它更可能是关于散列指针值。如果打算散列'uint32_t',它不应该是'hash(uint32_t)'或者至少'hash(uint32_t *)'? OTOH,'hash(void *)'是可以散列每种指针值的合理签名。 –

+1

是的,如果这是一个“诡计”问题,那么你也需要知道常常不是这种情况的“诡计”。 – Larry

+0

@ T.C。已更新以处理所有指针类型。 – Barry

4
  1. 恕我直言,你想象这些问题:) 的例子是从这里取:reinterpret_cast 因此,最好是看看例子在文章的上下文。

  2. 的问题是清楚的,但是当我读完它,我在我的第一分钟开始的解决方案无疑所有评论使用的reinterpret_cast(我无论如何都会把它作为一个答案,即使没有上下文)

+2

Woah,寻找原始来源的要点。好吧,它最终是一个MSDN文档错误(或者,至少是一个危险的不可移植的正式示例)。人物。 –

+0

尽管如此,我在想什么?我认为这个小组一般认为他们在技术上是准确的? –

+0

@PreferenceBean我把这个问题看作是面试中很多问题中的一个。你问这个问题就好像这个问题是关于面试的唯一问题。 – StahlRat

相关问题