2016-02-19 48 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

相關問題