2011-07-28 82 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); 
}