2012-09-12 91 views
4

我有一個unsigned char*。通常這指向一大塊數據,但在某些情況下,指針是數據,即。將int值賦給unsigned char*指針(unsigned char* intData = (unsigned char*)myInteger;),反之亦然。將指針轉換爲浮點數?

但是,我需要用float值來做到這一點,它不斷給我轉換錯誤。

unsigned char* data; 
float myFloat = (float)data; 

我該怎麼做?

+0

你不能,至少不容易。如果沒有一些神奇的黑客攻擊,這將永遠不會包含有效的信息,除非輸入是正確的IEEE格式。 –

+0

@ RichardJ.RossIII,除非你知道我不知道的東西(這不是不太可能,考慮到這是C++),你可以很容易地做到這一點。 –

+0

在您的平臺上,sizeof(unsigned char *)是否等於sizeof(float)?如果不是的話,那麼你究竟期待做什麼呢? (不要介意一般行爲的可怕的不確定性...) – Nemo

回答

2

如果你的編譯器支持它(GCC沒有),然後使用一個工會。根據C++標準,這是未定義的行爲。

union { 
    unsigned char* p; 
    float f; 
} pun; 

pun.p = data; 
float myFloat = pun.f; 

這工作,如果sizeof(unsigned char *) == sizeof(float)。如果指針大於浮點數,那麼你必須重新考慮你的策略。

請參閱type punning上的維基百科文章,尤其是有關use of a union的部分。

GCC允許使用聯合進行類型雙擊,只要您直接使用聯合而不是聯合類型轉換... see this IBM discussion on type-pun problems瞭解使用GCC進行類型雙擊的正確和不正確的方法。

另請參閱維基百科關於strong and weak typing的文章以及關於type punning and strict aliasing的深入研究文章。

+0

這不是一種不常見的聯合使用方法,但是在C++中,這會導致兩個未定義的行爲:首先它訪問聯合的非活動成員(即,它訪問的是除最後設置的成員之外的成員)。其次,如果它按預期工作,那麼它會違反嚴格的別名,通過不相關類型(float)的glvalue訪問一種類型的對象(unsigned char *)。 – bames53

+0

不嚴格的別名涉及引用相同的內存位置和指向基本不同類型的指針嗎?這不是這裏發生的事情。看到這個SO問題http://stackoverflow.com/questions/2906365/gcc-strict-aliasing-and-casting-through-a-union。 – amdn

+0

嚴格的別名規則是「如果程序試圖通過以下類型之一以外的glvalue訪問對象的存儲值,則行爲未定義:」(3.10p10)該代碼正在訪問存儲的「 unsigned char *'對象通過'float'類型的glvalue。嚴格別名規則列出的任何類型均未涵蓋此情況。 – bames53

-1
unsigned char* data; 
float myFloat = *(float*)data; 
+0

難道你不會忘記'&'嗎?如果float數據在指針本身中是*,你應該寫'&data'。 –

+1

即使寫入正確,這也是未定義的行爲。 –

+0

我敢打賭,這不是OP實際需要的 - 他們只是不知道如何提出問題 –

3

使用給定的變量來存儲其他數據的唯一正確的方法是複製數據逐字節:

template <typename T> 
void store(unsigned char * & p, T const & val) 
{ 
    static_assert(sizeof(unsigned char *) >= sizeof(T)); 

    char const * q = reinterpret_cast<char const *>(&val); 
    std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&p)); 
} 

用法:

unsigned char * p; 
store(p, 1.5); 
store(p, 12UL); 

匹配檢索功能:

template <typename T> 
T load(unsigned char * const & p) 
{ 
    static_assert(sizeof(unsigned char *) >= sizeof(T)); 

    T val; 
    char const * q = reinterpret_cast<char const *>(&p); 
    std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&val)); 

    return val; 
} 

用法:

auto f = load<float>(p); 
+0

我認爲你的'load'聲明關閉了。您不指定返回值。 –

+0

@ RichardJ.RossIII:謝謝,修復! –

4

bit_cast:

template <class Dest, class Source> 
inline Dest bit_cast(Source const &source) { 
    static_assert(sizeof(Dest)==sizeof(Source), "size of destination and source objects must be equal"); 
    static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable."); 
    static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable"); 

    Dest dest; 
    std::memcpy(&dest, &source, sizeof(dest)); 
    return dest; 
} 

用法:

char *c = nullptr; 
float f = bit_cast<float>(c); 
c = bit_cast<char *>(f);