我正在按照本教程在C ++中使用OpenAL:http://enigma-dev.org/forums/index.php?topic=730.0
正如您在教程中看到的那样,它们会使一些方法未实现,而我在实现file_read_int32_le(char *,FILE *)和file_read_int16_le(char *,FILE *)时遇到了问题。显然它应该做的是从文件加载4个字节(或者在int16的情况下加2,我猜...),将它从little-endian转换为big endian然后将其作为无符号整数返回。这是代码:
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中)它表示* buffer的十六进制值是0x72,这只是一个字节。当我使用malloc(4)创建newBuffer时,我得到一个4字节缓冲区(* newBuffer类似于0xC0000003),然后在操作之后变为0x72000000。我假设我正在寻找的结果是0x00000027(编辑:实际上是0x00000072),但我将如何实现这一目标?是否与char * buffer和unsigned int * newBuffer之间的转换有关?
答案 0 :(得分:1)
有一系列称为“htons / htonl / hton”的函数,其唯一目的是将“主机”转换为“网络”字节顺序。
http://beej.us/guide/bgnet/output/html/multipage/htonsman.html
每个函数都有一个相反的倒数。
现在,这些函数无法帮助您,因为它们本质上是从您的主机特定字节顺序转换的,所以请使用此答案作为查找所需内容的起点。通常,代码不应该假设它所处的架构。
Intel ==“Little Endian”。 网络==“Big Endian”。
希望这能让你走上正轨。
答案 1 :(得分: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);
}
答案 2 :(得分:1)
是的,*缓冲区将在Xcode的调试器中读取为0x72,因为缓冲区是指向char的指针。
如果缓冲区指向的内存块中的前四个字节是(十六进制)72 00 00 00,则返回值应为0x00000072,而不是0x00000027。字节应该被交换,而不是组成每个字节的两个“nybbles”。
此代码泄露了malloc'd的内存,无论如何你都不需要malloc。
您的字节交换在PowerPC或68K Mac上是正确的,但在Intel Mac或基于ARM的iOS上则不行。在这些平台上,您不必进行任何字节交换,因为它们本身就是小端的。
Core Foundation提供了一种更轻松地完成此任务的方法:
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);
}