2012-08-02 19 views
1

我知道C++ 11有一些標準的工具可以從未對齊的內存中獲得整數值。這樣的事情怎麼會以更標準的方式寫出來呢?如何以標準方式從未對齊的內存中獲取值?

template <class R> 
inline R get_unaligned_le(const unsigned char p[], const std::size_t s) { 
    R r = 0; 
    for (std::size_t i = 0; i < s; i++) 
     r |= (*p++ & 0xff) << (i * 8); // take the first 8-bits of the char 
    return r; 
} 

要利用存儲在豆蔻-endian順序的值,然後你可以寫:

uint_least16_t value1 = get_unaligned_le<uint_least16_t > (&buffer[0], 2); 
uint_least32_t value2 = get_unaligned_le<uint_least32_t > (&buffer[2], 4); 

回答

1

積分值是如何進入未對齊內存的? 如果他們是memcpy編輯,那麼您可以使用memcpy將它們取出。 如果從文件或網絡中讀取它們,您必須知道它們的格式:它們是如何寫入的。如果他們是四字節 大端二進制補碼(通常的網絡格式),那麼就有 像:

//  Supposes native int is at least 32 bytes... 
unsigned 
getNetworkInt(unsigned char const* buffer) 
{ 
    return buffer[0] << 24 
     | buffer[1] << 16 
     | buffer[2] << 8 
     | buffer[3]; 
} 

這對於任何無符號類型的工作,只要你的目標 的類型是至少與您輸入的類型一樣大。對於簽名,它取決於 您想要的移動性如何。如果所有潛在目標機器都是2的補碼,並且將與您的輸入類型具有相同尺寸的整數類型,那麼您可以使用與上面的 完全相同的代碼。如果你的本機是一個補碼爲36的機器(例如 是Unisys主機),並且你正在讀取帶符號的網絡格式整數 (32位2的補碼),那麼你需要一些額外的邏輯。

+0

謝謝。基本上有8位長的無符號字符正在從設備寫入主機,設備總是將它們寫入小端順序(我已經解決了我的問題)現在還有一個不明確的問題是:如果主機arch中的字節長度超過8位,會發生什麼情況?舉個例子,假設它們是16位長要寫兩個8位uchars,設備是否需要消耗兩個字節主機(只有第一個8位有意義)還是設備只使用一個字節? – Martin 2012-08-02 09:58:30

+0

@Martin這取決於編寫代碼的人是誰,但是在邏輯上,對於在機器外部可見的任何東西,我期望只使用字節的低8位。 (如果你通過移位和屏蔽來寫入int,那麼這會自動從代碼中跳出來,如果編碼者認爲他會聰明並使用memcpy,那麼最終可能會丟失每一個第8位輸出)。 – 2012-08-02 10:05:08

1

與往常一樣,創建所需的變量並填充它的字節方式:

#include <algorithm> 
#include <type_traits> 

template <typename R> 
R get(unsigned char * p, std::size_t len = sizeof(R)) 
{ 
    assert(len >= sizeof(R) && std::is_trivially_copyable<R>::value); 

    R result; 
    std::copy(p, p + sizeof(R), static_cast<unsigned char *>(&result)); 
    return result; 
} 

這隻適用於普通的可複製類型,儘管如果您有來自其他地方的額外保證,您可以將其用於重要類型。

+0

是不是static_assert(sizeof(R)> = len)...和std :: copy(p,p + len ...因爲我想從p中創建len字節的值,我也是在我的函數名中加上_le來強調它僅適用於litte-endian機器,我認爲它在這裏是一樣的 – Martin 2012-08-02 09:13:03

+0

@Martin:對於「相同的排序」,它應該是'_se',如果有的話......但應該清楚的是,這不會讓你持久地或跨平臺地序列化數據 – 2012-08-02 09:21:55