2009-05-27 44 views
0

基本上我想要做的是,根據某些變量,將void指針轉換爲不同的數據類型。例如(在「投」變量只是爲了瞭解我點的東西):Casting void指針,取決於數據(C++)

void* ptr = some data; 
int temp = some data; 
int i = 0; 

... 

if(temp == 32)  cast = (uint32*) 
else if(temp == 16) cast = (uint16*) 
else    cast = (uint8*) 

i = someArray[*((cast)ptr)]; 

是否有在C++中,可以做這樣的事情(因爲你不能真正分配一個變量是什麼只是(uint32 *)或類似的東西)?我很抱歉,如果這不明確,任何幫助將不勝感激。

+0

爲什麼不只是在做測試時施放? if(temp == 32)index =(uint32 *)ptr; //等 – 2009-05-27 01:06:38

+0

是的,這是顯而易見的方式,但是如果我這樣做了,我會需要數百個if ... elses。 if(temp == 32)i = someArray [* index32]; else if(temp == 16)i = someArray [* index16];等我希望有一些簡單的方法來做到這一點,如上所述。 – Joel 2009-05-27 01:13:35

+0

你還需要數百個if/elses? – 2009-05-27 01:17:41

回答

5

「正確」 的方式:

union MyUnion 
{ 
    uint32 asUint32; 
    uint16 asUint16; 
    uint8 asUint8; 
} 

uint32 to_index(int size, MyUnion* ptr) 
{ 
    if (size== 32) return ptr->asUint32; 
    if (size== 16) return ptr->asUint16; 
    if (size== 8) return ptr->asUint8; 
} 

i = someArray[to_index(temp,ptr)] 

[更新:固定啞錯字]

+0

在三個條件中,你是指「大小」而不是「溫度」? – 2009-05-27 01:46:38

+0

哎呦......是啊......修好了。 – 2009-05-27 02:31:39

0

聽起來好像你是在工會之後,或者如果你使用Visual Studio _variant_t。或者,也許typeinfo()會有幫助嗎? (說實話,我不太確定你想要做什麼)。至於劇組,你可以投任何東西 - 這就是C++的危險(如果你真的很小心,那麼就是強大的)。

另請注意,在大多數平臺中指針值爲32位或64位,因此無法將uint64存儲在32位平臺的void *中。

最後,也許這就是你想要什麼:

void* p = whatever; 

uint32 x = (uint32)p; 

也許

uint32 source = 6; 

void* p = &source; 

uint32 dest = *((uint32*)p); 

void* p = 
1

一個清潔的解決方案:

uint32 to_index(int temp, void* ptr) { 
    if (temp == 32) return *((uint32*)ptr); 
    if (temp == 16) return *((uint16*)ptr); 
    if (temp == 8) return *((uint8*)ptr); 
    assert(0); 
} 

i = someArray[to_index(temp,ptr)] 
0

如果你鎖定在使用無效PTR,絕對需要調用[]有不同的類型:

template <typename cast_to> 
inline 
int get_int_helper(someArray_t someArray, void* ptr) { 
    return someArray[*static_cast<cast_to*>(ptr)]; 
} 

int get_int(someArray_t someArray, void* ptr, int temp) { 
    switch (temp) { 
     case 32: return get_int_helper<uint32>(someArray,ptr); 
     case 16: return get_int_helper<uint16>(someArray,ptr); 
     default: return get_int_helper<uint8>(someArray,ptr); 
    } 
} 

然而,正如其他人指出,有可能有更好的/其他的方式來做到這一點。最有可能的是,無論你有多少個數組,都沒有多個操作符[],所以它不需要不同的類型。另外,你可以使用boost :: variant來保存這種類型的區別聯合,這樣你就不必臨時通過

2

顯然,boost::variant是要走的路。它已經存儲一個類型標籤,使您不可能轉換爲錯誤的類型,使用編譯器的幫助來確保這一點。這是它是如何工作的

typedef boost::variant<uint32_t*, uint16_t*, uint8_t*> v_type; 

// this will get a 32bit value, regardless of what is contained. Never overflows 
struct PromotingVisitor : boost::static_visitor<uint32_t> { 
    template<typename T> uint32_t operator()(T* t) const { return *t; } 
}; 

v_type v(some_ptr); // may be either of the three pointers 

// automatically figures out what pointer is stored, calls operator() with 
// the correct type, and returns the result as an uint32_t. 
int i = someArray[boost::apply_visitor(PromotingVisitor(), v)]; 
0

看來你想存儲「cast」函數,它需要一個void *併產生一個無符號整數。所以,使其成爲一個功能:

std::map<int, boost::function<unsigned(*)(void*)> casts; 
template <typename T> unsigned cast(void* v) { return *(T*)v; } 
casts[32] = cast<uint32>; 
casts[16] = cast<uint16>; 
casts[8] = cast<uint8>; 
casts[128] = MySpecialCastFromDouble; 

void* foo = getFoo(); 
unsigned bar = casts[16](foo);