2014-01-10 87 views
1

我不知道這是否是正確的,我已經測試過它,似乎有些字節是關閉... 基本上,我有以下幾點:無符號字符數組鑄造長長

unsigned char szBuffer[1024] = {0}; 
long long nValue = 1334553536; 
memcpy(szBuffer, (char*)&nValue, sizeof(long long)); 

// 

long long nNewValue = reinterpret_cast<long long>(szBuffer); 
printf(nNewValue); //prints out a smaller number than previously stated 

會任何人都會指出我出錯的地方?謝謝。

+0

'printf'的第一個參數是一個格式字符串; 'printf(rNewValue)'可能不會編譯。請發佈真實的代碼。 –

+0

最初它是std :: cout,但後來我意識到我偶然添加了C標記,因此我將其更改爲printf()而不考慮它是否會編譯。這只是一個小小的改變。其餘的編譯。 –

+0

C標籤不再存在。再次,請張貼真實的代碼,複製並粘貼您實際編制的代碼。如果你知道你的代碼中有什麼錯誤是相關的,你就不需要問這個問題。 http://sscce.org/ –

回答

4

您正在將nNewValue設置爲szBuffer的地址,而不是從該地址讀取數據。用途:

long long nNewValue = *reinterpret_cast<long long*>(szBuffer); 
+0

謝謝,這似乎工作。猜猜我必須再次參加我的演員... –

+0

是的,它*似乎*工作。但你怎麼知道'szBuffer'正確對齊以容納一個'long long'對象?看[我的回答](http://stackoverflow.com/a/21050083/827263)。 –

+0

我不這樣做 - 這就是爲什麼我要更多地瞭解緩衝區對齊,並找出你的意思。謝謝。 –

1

更改本聲明

long long nNewValue = reinterpret_cast<long long>(szBuffer); 

long long nNewValue = *reinterpret_cast<long long *>(szBuffer); 
+0

壞主意。你怎麼知道'szBuffer'對於一個'long long'對象適當的對齊? –

+0

@凱斯湯普森我同意。他應該指定緩衝區的對齊方式 –

+0

指定對齊方式不可能是最好的解決方案。我們不知道OP的真正目標是什麼,但有很多更清潔的替代品。 –

0

下面是我的系統上工作程序的修改版本(擴展爲一個完整的程序):

#include <iostream> 
#include <cstring> 
int main() { 
    unsigned char szBuffer[1024] = {0}; 
    long long nValue = 1334553536; 
    std::memcpy(szBuffer, &nValue, sizeof(long long)); 
    long long nNewValue = *(reinterpret_cast<long long*>(&szBuffer)); 
    std::cout << nValue << "\n" << nNewValue << "\n"; 
} 

memcpy的前兩個參數的類型爲void*,所以你不需要施放它們;如果你確實投了它們(是否在C++中棄用了該轉換?),則應該投射到void*而不是char*

分配到nNewValue緩衝器的地址轉換爲long long*,然後取消引用轉換後的值。

但這是一個壞主意。克++給我所轉換的指針的間接引用的警告:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 

此外,存在不保證szBuffer,這是unsigned char陣列,被正確地對準,使得它的前幾個字節可以安全地作爲待處理long long對象。您最可能使用的x86或x86_64系統容許存在未對齊的內存訪問,但並非所有系統都這樣做。

指針轉換通常是不安全的,除非你知道正好你在做什麼。

如果要重新解釋字符數組的一部分作爲其他類型的對象,如果您確實需要將內存本身解釋爲不同類型的對象,或使用memcpy,則可以使用聯合。 (即便如此,要確保你真的需要做到這一點,很可能是你不這樣做在大多數情況下,如果要存儲一個long long對象,你應該只定義一個long long對象。)

+0

如果你所說的是不安全的 - 那麼我會考慮做其他事情。把long long的值作爲ANSI字符,將sprintf()放入緩衝區,然後將atoll()放回long long?這會更好嗎? –

+0

@AndyCarter:那不會做同樣的事情。首先,「ANSI字符對微軟的8位字符集之一(如Windows-1252)來說是不恰當的,即使MS不再這麼稱呼它,沒有字符的值爲1334553536,所以這種方法無法工作。如果你的目標是把'1334553536'作爲'long long'的值,你已經用'nValue'取得了,並且不需要使用緩衝區。如果你的目標是別的,你需要告訴我們你正在努力完成什麼(再一次,請更新你的問題,告訴我們你的實際代碼) –

+0

你稍微誤解了我,當然沒有1334553536的字符。我的想法是實際上把「字符串」本身1334553536放入緩衝區,佔用10個字節,但我強調,在我的項目中有很多代碼,我確定你不是別人有時間去查看它。說的是我正在爲網絡程序實現一個「ping/ms」計數器,你知道 - 從1開始計算當前時間(以毫秒爲單位) 970,發送數據包,接收相同的數據包,再次獲取當前時間,並減去差異以及任何開銷。 –