2010-01-11 102 views
0

我有一個有十六進制值的字節數組,我最初把這些值放在一個無符號長整型中。 我現在通過Ubuntu使用32位處理器。但是,我可能必須將此程序移植到64位處理器。關於字節數組到長長(64位)數組與長(32位)的問題

現在我知道strtoul函數,但因爲我能夠轉換它會通過直接任務的任何問題,我沒有打擾與該功能。我之所以把它放在一個沒有簽名的long中是因爲我在考慮小/大的endian問題,所以使用像signed long這樣的寄存器只會爲我處理這個問題,而不管處理器如何。但是現在我一直在想我的程序如何在64位處理器上工作。

因爲我在32位處理器,它可能只認識32位長VS 64位處理器只能識別64位長,這使我的簽署多頭排列處於危險之中。所以,爲了解決這個問題,我只是把這個簽名數組做了很長時間。這會解決我的擔憂嗎?還是我需要做別的事情?

一些幫助和解釋將不勝感激。我的所有代碼都在C++中。

回答

2

而不是使用longlong long你應該使用像uint32_t,或類似的東西一個typedef的,所以它可以在所有平臺上的32位,除非這是不是你想要的?

看來你確實有字節順序一個潛在的問題不過,如果你只做:

char bytes[4] = {0x12, 0x23, 0xff, 0xed}; 
long* p_long = reinterpret_cast<long*>(bytes); 

std::cout << std::hex << *p_long << std::endl; // prints edff2312 on a little endian platform, 1223ffed on a big endian one. 

因爲當解釋爲一個整數將根據字節序變更字節的實際值。關於轉換排序here有一個很好的答案。

+0

我實際上在做以下操作 字節輸出[somesize]; memset(output,0x00,somesize); memset 我用散列值填充它,然後做一個直接分配的循環。 很長很長的另一個輸出[somesize]; 運行for循環並執行任務。 現在你說這仍然是一個永恆的問題? 我會看看你發給我的是什麼。 – djones2010 2010-01-11 23:40:27

+0

是的,我不完全確定你在說什麼,但我認爲是。 (你可以編輯問題添加一些代碼來演示你在做什麼?) – James 2010-01-12 00:01:53

+0

我可以使用int64_t bswap_64(int64_t x)。我可以得到一個例子,我可以如何使用這個與十六進制值的字節數組? – djones2010 2010-01-12 16:59:37

1

你可能想看看SO 2032744作爲一個大端到小端問題的例子。

我不確定你使用寄存器意味着什麼,可以解決你的endian-ness問題。我們需要查看代碼才能知道。但是,如果您需要通過不同機器之間的線路傳輸整數值,則需要確保正確處理大小和字節順序。這意味着兩端必須就如何處理它達成一致 - 即使他們實際上以不同的方式做事。

複製的字節數組成Intel平臺上的「長」將從複製同一陣列成「長」在SPARC平臺上產生不同的結果。要通過註冊,您必須使用類似於以下代碼:

void  st_uint4(Uint4 l, char *s) 
{ 
    s += sizeof(Uint4) - 1; 
    *s-- = l & 0xFF; 
    l >>= 8; 
    *s-- = l & 0xFF; 
    l >>= 8; 
    *s-- = l & 0xFF; 
    l >>= 8; 
    *s = l & 0xFF; 
} 

Uint4 ld_uint4(const char *s) 
{ 
    int i; 
    Uint4 j = 0; 

    for (i = 0; i < 4; i++) 
    { 
     j = (j << 8) | (*s++ & 0xFF); 
    } 
    return(j); 
} 

有多種方法可以編寫該代碼。


尋址的評論:

當整個機器的數據處理,你必須非常小心。顯示的兩個函數是相互顛倒的。 'ld_uint4()'函數接受一個字節數組並將其加載到一個4字節的有符號整數中(假設您有一個Uint4的typedef,映射到一個4字節的有符號整數 - uint32_t來自inttypes.h或stdint.h是好打賭)。 st_uint4()函數執行反向操作。此代碼使用big-endian存儲格式(MSB在字節數組中首先使用),但在兩種類型的平臺上都使用相同的代碼(沒有性能優勢 - 也沒有條件編譯,這可能更重要)。你可以編寫代碼來使用little-endian存儲;你可以編寫代碼,以便在一種類型的機器上比其他類型的機器更少受到懲罰。

瞭解磁盤上的數據佈局至關重要 - 仔細定義並以平臺中立的方式進行定義也至關重要。處理(單字節代碼集)字符串很簡單;處理寬字符字符串(UTF-16或UTF-32)就像處理整數一樣 - 如果你願意,你可以使用與上面的代碼類似的代碼(例如,我已經預先打包了這樣的函數 - 我只是複製Uint4版本;我也有SintN函數 - 對於複製的東西,差異並不重要,但對於內存比較,signed和unsigned值的比較技術是不同的)。

處理float和double更棘手 - 儘管如果你可以安全地假設IEEE 754格式,它主要是你面對的一個大端到小端的問題(也許是一些工會的狡猾問題)。我使用的代碼庫與葉/雙浮動平臺相關(這是一個令人討厭的問題,但是可以追溯到IEEE 754之前的日子無處不在),所以我沒有平臺中立的代碼。也要小心路線;英特爾芯片允許未對齊訪問,但其他芯片(SPARC,PowerPC)不支持,或產生大量開銷。這意味着,如果您複製一個4字節的值,則如果您執行簡單複製,則源地址和目標地址必須爲4字節對齊;上面的存儲/加載函數沒有這個問題,可以處理任意的對齊。再次警惕過度優化(過早優化)。

+0

喬納森,因爲我還是比較新的所有這一切我想我只是在運行32位的ubuntu 9.1中編譯一個程序,其中長爲4字節,然後將其移植到64位的太陽站。因此,我目前所瞭解的是,不僅64位的長度會變大而且不同,而且讀取的方式也會顛倒,使得數值不同。所以,如果我使用ld_unit4函數你有他們會它扭轉數組中的十六進制值?對於我來說,我從來沒有真正做過任何點點算術。謝謝。 – djones2010 2010-01-12 17:04:08

1

1)簽名與未簽名不會讓你免受endian問題的影響。唯一的數據類型endian不可知是一個字節(char)。如果你有兩臺不同的機器,用其他所有的東西你需要交換endian

2)一個64位的機器總是會爲你提供某種類型的32位整數,你可以使用它來將值從你的數組中拉出來。所以這不應該是一個問題,只要你確定兩臺機器都使用32位int(並且你可能編碼數據的字節順序)。