Проблема преобразования порядка байтов - PullRequest
1 голос
/ 28 июля 2011

Я следую этому руководству по использованию OpenAL в C ++: http://enigma -dev.org / forums / index.php? Topic = 730.0

Как вы можете видеть из учебника, они оставляют несколько методов не реализованными, и у меня возникают проблемы с реализацией file_read_int32_le (char *, FILE *) и file_read_int16_le (char *, FILE *). Очевидно, что это должно сделать, это загрузить 4 байта из файла (или 2 в случае с int16, я думаю ...), преобразовать его из младшего к старшему и затем вернуть его как целое число без знака. Вот код:

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, что составляет всего один байт. Когда я создаю newBuffer с помощью malloc (4), я получаю 4-байтовый буфер (* newBuffer - это что-то вроде 0xC0000003), который после операций становится 0x72000000. Я предполагаю, что результат, который я ищу, равен 0x00000027 (правка: фактически 0x00000072), но как мне этого добиться? Это как-то связано с преобразованием между буфером char * и беззнаковым int * newBuffer?

Ответы [ 3 ]

1 голос
/ 28 июля 2011

Я использовал следующее для целочисленных типов. На некоторых платформах это небезопасно для нецелых типов.

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);
}
1 голос
/ 28 июля 2011

Да, * буфер будет считываться в отладчике Xcode как 0x72, потому что буфер является указателем на символ.

Если первые четыре байта в блоке памяти, на который указывает буфер, являются (шестнадцатеричными) 72 00 0000, тогда возвращаемое значение должно быть 0x00000072, а не 0x00000027.Байты должны быть поменяны местами, но не два «куска», составляющих каждый байт.

Этот код пропускает память, которую вы используете malloc, и вам все равно здесь не нужно 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);
}
1 голос
/ 28 июля 2011

есть целый ряд функций, называемых "htons / htonl / hton", единственной целью которых в жизни является преобразование порядка байтов из "хоста" в "сеть".

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

Каждая функция имеет обратную функцию, которая делает обратное.

Теперь, эти функции не обязательно помогут вам, потому что они по сути конвертируют из вашего порядка байтов вашего хоста, поэтому, пожалуйста, просто используйте этот ответ в качестве отправной точки, чтобы найти то, что вам нужно. Как правило, код никогда не должен делать предположения о том, на какой архитектуре он работает.

Intel == "Little Endian". Сеть == "Big Endian".

Надеюсь, это приведет вас на правильный путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...