2011-07-28 45 views
1

我下面這個教程在C使用的OpenAL ++:http://enigma-dev.org/forums/index.php?topic=730.0問題轉換字節序

正如您在本教程中看到,他們留下的一些方法未實現,和我有麻煩實施file_read_int32_le(字符*,FILE *)和file_read_int16_le(char *,FILE *)。顯然它應該做的是從文件中加載4個字節(或者在int16的情況下加2個,我猜...),將它從小端轉換爲大端,然後將其作爲無符號整數返回。下面的代碼:

static unsigned int file_read_int32_le(char* buffer, FILE* file) { 
    size_t bytesRead = fread(buffer, 1, 4, file); 
    printf("%x\n",(unsigned int)*buffer); 
    unsigned int* newBuffer = (unsigned int*)malloc(4); 
    *newBuffer = ((*buffer << 24) & 0xFF000000U) | ((*buffer << 8) & 0x00FF0000U) | ((*buffer >> 8) & 0x0000FF00U) | ((*buffer >> 24) & 0x000000FFU); 
    printf("%x\n", *newBuffer); 
    return (unsigned int)*newBuffer; 
} 

調試時(XCode中),它說的*緩衝區的十六進制值是0x72,這是隻有一個字節。當我使用malloc(4)創建newBuffer時,我得到一個4字節的緩衝區(* newBuffer就像0xC0000003),然後在操作之後變成0x72000000。我假設我正在尋找的結果是0x00000027(編輯:實際上是0x00000072),但我將如何實現這一目標?是否在char *緩衝區和unsigned int * newBuffer之間進行轉換?

+1

實際上,該值將是0x00000072,不是0x00000027。基本上,它是交換字節順序,而不是nbble順序。 –

+0

好喊。編輯。 – benwad

+0

爲什麼該方法提供緩衝區和文件指針?這是不直觀的。 – trojanfoe

回答

1

是,*緩衝區將在Xcode的閱讀調試器爲0x72,因爲緩衝區是指向字符的指針。

如果緩衝區指向的內存塊中的前四個字節是(十六進制)72 00 00 00,那麼返回值應該是0x00000072,而不是0x00000027。字節應該被交換,但不是構成每個字節的兩個「nybbles」。

此代碼泄漏你malloc'd的內存,並且無論如何你都不需要malloc。

在PowerPC或68K Mac上您的字節交換是正確的,但不是在Intel Mac或基於ARM的iOS上。在這些平臺上,你不必做任何字節交換,因爲它們本質上是小端的。

核心基金提供了一種方法都更容易做到這一點:

static uint32_t file_read_int32_le(char* buffer, FILE* file) { 
    fread(buffer, 1, 4, file);   // Get four bytes from the file 
    uint32_t val = *(uint32_t*)buffer; // Turn them into a 32-bit integer 

    // Swap on a big-endian Mac, do nothing on a little-endian Mac or iOS 
    return CFSwapInt32LittleToHost(val); 
} 
1

這裏有一整套被稱爲「htons/htonl/hton」的功能,其唯一目的是從「主機」轉換爲「網絡」字節順序。

http://beej.us/guide/bgnet/output/html/multipage/htonsman.html

每個函數都有一個倒數,做相反。

現在,這些函數不會幫助你,因爲它們從你的主機特定的字節順序內在轉換,所以請使用這個答案作爲起點來找到你需要的東西。一般來說,代碼不應該對它所在的架構做出假設。

Intel ==「Little Endian」。 網絡==「Big Endian」。

希望這能讓你走上正軌。

1

我已經使用了下面的整數類型。在某些平臺上,非整型類型不安全。

template <typename T> T byte_reverse(T in) { 
    T out; 
    char* in_c = reinterpret_cast<char *>(&in); 
    char* out_c = reinterpret_cast<char *>(&out); 
    std::reverse_copy(in_c, in_c+sizeof(T), out_c); 
    return out; 
}; 

所以,把在你的文件閱讀器(你爲什麼經過緩衝的,因爲它似乎,這可能是暫時的)

static unsigned int file_read_int32_le(FILE* file) { 
    unsigned int int_buffer; 
    size_t bytesRead = fread(&int_buffer, 1, sizeof(int_buffer), file); 
    /* Error or less than 4 bytes should be checked */ 
    return byte_reverse(int_buffer); 
}