Изменить:
Удалены комментарии о том, как эффективно хранить данные всегда с прямым порядком байтов и заменять их на машинные, так как спрашивающий не упомянул, что другая программа записывает его данные (что является важной информацией).
Тем не менее, если данные нуждаются в преобразовании из любого порядка байтов к большому и от большого к хосту endian, ntohs / ntohl / htons / htonl являются лучшими методами, наиболее элегантными и непревзойденными по скорости (поскольку они будут выполнять задачи на аппаратном уровне, если процессор это поддерживает, вы не сможете победить).
Что касается double / float, просто сохраните их в целых числах путем приведения в память:
double d = 3.1234;
printf("Double %f\n", d);
int64_t i = *(int64_t *)&d;
// Now i contains the double value as int
double d2 = *(double *)&i;
printf("Double2 %f\n", d2);
Оберните это в функцию
int64_t doubleToInt64(double d)
{
return *(int64_t *)&d;
}
double int64ToDouble(int64_t i)
{
return *(double *)&i;
}
Спрашивающий предоставил эту ссылку:
http://cocoawithlove.com/2008/04/using-pointers-to-recast-in-c-is-bad.html
как доказательство того, что кастинг плохой ... к сожалению, я могу только сильно не согласиться с большей частью этой страницы. Цитаты и комментарии:
Так же часто, как приведение через указатель
это на самом деле плохая практика и
потенциально рискованный код. Кастинг
через указатель имеет потенциал для
создавать ошибки из-за типа punning.
Это совсем не рискованно, и это также не плохая практика. Он может вызвать ошибки, если вы делаете это неправильно, точно так же, как программирование на C может вызвать ошибки, если вы делаете это неправильно, как и любое программирование на любом языке. По этому аргументу вы должны полностью прекратить программирование.
Тип штамповки
Форма указателя
алиасинг, где два указателя и ссылки
в то же место в памяти, но
представлять это место как другое
типы. Компилятор будет относиться как к
"каламбуры" как несвязанные указатели. Тип
наказание может вызвать
проблемы зависимости для любых данных
доступ через оба указателя.
Это правда, но, к сожалению совершенно не связано с моим кодом .
На что он ссылается, так это код:
int64_t * intPointer;
:
// Init intPointer somehow
:
double * doublePointer = (double *)intPointer;
Теперь doublePointer и intPointer указывают на одну и ту же область памяти, но рассматривают это как один и тот же тип. Это ситуация, которую вы должны решить с профсоюзом, все остальное довольно плохо. Плохо, что это не то, что делает мой код!
Мой код копируется по значению , а не по ссылке . Я бросил двойной указатель на int64 (или наоборот) и немедленно преобразил его. Как только функции возвращаются, указатель на что-либо не сохраняется. Есть int64 и double, и они совершенно не связаны с входным параметром функций. Я никогда не копирую указатель на указатель другого типа (если вы видели это в моем примере кода, вы сильно неправильно читали написанный мной код C), я просто передаю значение в переменную другого типа (в собственном месте памяти) , Таким образом, определение типа punning вообще не применяется, так как в нем говорится «ссылаются на одно и то же место в памяти», и здесь ничего не ссылается на одно и то же место в памяти.
int64_t intValue = 12345;
double doubleValue = int64ToDouble(intValue);
// The statement below will not change the value of doubleValue!
// Both are not pointing to the same memory location, both have their
// own storage space on stack and are totally unreleated.
intValue = 5678;
Мой код - не что иное, как копия памяти, просто написанная на C без внешней функции.
int64_t doubleToInt64(double d)
{
return *(int64_t *)&d;
}
Может быть записано как
int64_t doubleToInt64(double d)
{
int64_t result;
memcpy(&result, &d, sizeof(d));
return result;
}
Это не более того, так что нигде не видно типа. И эта операция также абсолютно безопасна, так же, как безопасна операция на языке C. Определяется, что double всегда должен быть 64-битным (в отличие от int, он не изменяется по размеру, он фиксирован на 64-битном), следовательно, он всегда будет соответствовать в переменную размера int64_t.