htonl (хост с длинной сетью) и htons (короткая сеть с хостом) будут переходить с любой платформы, на которой вы находитесь, на big-endian. Это было потому, что в те дни большинство сетевых хостов работали в форме UNIX, в которой использовался нативный big-endian.
ntohl и ntohs преобразуют big endian в native независимо от вашей платформы. Если вы находитесь на платформе с прямым порядком байтов, это будет неактивный оператор.
Помимо порядка байтов, другой потенциальной проблемой переносимости является размер короткого и длинного. ntohl прочитает 4 байта и преобразует их в 32-разрядное целое число. Следовательно, целевое значение int должно быть не менее 32 бит, чтобы удерживать его, оно не должно быть точно такой длины. ntohs читает 2 байта и преобразует в короткое целое число из 16 бит. Обратите внимание, что если ваша собственная платформа использует более 32 бит для длинных или 16 бит для коротких, вы должны решить проблему со знаком, если они являются целыми числами со знаком (потому что фактический тип для ntohl - без знака).
Поскольку все больше машин, в том числе и Linux, используют процессоры Intel с порядковым порядком байтов, гораздо чаще теперь вы используете этот формат в качестве формата «по умолчанию» и получаете изменения в формате с прямым порядком байтов. В таком случае вы можете захотеть написать собственные макросы для преобразования в формат с прямым порядком байтов (на платформе с прямым порядком байтов они будут недоступны).
Кстати, для реверсирования байтов вы можете использовать std :: reverse, и вам понадобятся два указателя, один из которых указывает на первый байт, а другой - на один после последнего байта.
Вы также можете реализовать «байт-своп», и тогда ваш правый указатель должен быть на последнем байте, а не на одном конце. Вы byteswap, как это:
void byteswap( unsigned char & byte1, unsigned char & byte2 )
{
byte1 ^= byte2;
byte2 ^= byte1;
byte1 ^= byte2;
}
Для реализации в C (а не в C ++) вы бы использовали указатель, а не ссылку в качестве параметра.
В приведенном вами примере, похоже, файл хранится в 32-битном порядке байтов с прямым порядком байтов (то есть в сети) в соответствии со своей спецификацией, поэтому вы можете просто использовать ntohl, однако ntohl принимает беззнаковое целое как параметр. Таким образом, исправьте ваш код следующим образом:
uint32_t count = 0;
myfile.open ("truss.rst", ios::binary);
myfile.read(reinterpret_cast<char*>(&count), sizeof(uint32_t));
// ideally validate that the read succeeded
count = ntohl( count );
Одна из слабостей в iostream, по моему мнению, что вы должны сделать это. Тот, кто написал это, никогда не любил концепцию двоичного ввода / вывода. Конечно, если вы пишете это на C, а не на C ++, вы должны использовать FILE*
и fread
.