C Функция для преобразования массива float в байты
Я пытаюсь создать функцию, которая примет переменную float и преобразует ее в массив байтов. Я нашел фрагмент кода, который работает, но хотел бы повторно использовать его в функции, если это возможно.
Я также работаю с окружением Arduino, но я понимаю, что он принимает большинство языков C.
В настоящее время работает:
float_variable = 1.11;
byte bytes_array[4];
*((float *)bytes_array) = float_variable;
Что я могу изменить здесь, чтобы эта функция работала?
float float_test = 1.11;
byte bytes[4];
// Calling the function
float2Bytes(&bytes,float_test);
// Function
void float2Bytes(byte* bytes_temp[4],float float_variable){
*(float*)bytes_temp = float_variable;
}
Я не так хорошо знаком с указателями и такими, но я читал, что (float) использует кастинг или что-то еще?
Любая помощь будет принята с благодарностью!
Приветствия
* EDIT: SOLVED
Здесь моя последняя функция, которая работает в Arduino для всех, кто находит это. В ответах ниже есть более эффективные решения, но я думаю, что это хорошо понять.
Функция: преобразует входную переменную float в массив байтов
void float2Bytes(float val,byte* bytes_array){
// Create union of shared memory space
union {
float float_variable;
byte temp_array[4];
} u;
// Overite bytes of union with float variable
u.float_variable = val;
// Assign bytes to input array
memcpy(bytes_array, u.temp_array, 4);
}
Вызов функции
float float_example = 1.11;
byte bytes[4];
float2Bytes(float_example,&bytes[0]);
Спасибо за помощь, я так много узнал о указателях и ссылках за последние 20 минут, Cheers Stack Overflow!
Ответы
Ответ 1
Проще всего сделать союз:
#include <stdio.h>
int main(void) {
int ii;
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = 1.234;
for (ii=0; ii<4; ii++)
printf ("byte %d is %02x\n", ii, thing.bytes[ii]);
return 0;
}
Выход:
byte 0 is b6
byte 1 is f3
byte 2 is 9d
byte 3 is 3f
Примечание: нет никакой гарантии относительно порядка байтов… это зависит от архитектуры вашего компьютера.
Чтобы заставить вашу функцию работать, сделайте это:
void float2Bytes(byte bytes_temp[4],float float_variable){
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = float_variable;
memcpy(bytes_temp, thing.bytes, 4);
}
Или действительно взломать это:
void float2Bytes(byte bytes_temp[4],float float_variable){
memcpy(bytes_temp, (unsigned char*) (&float_variable), 4);
}
Примечание. В любом случае я обязательно копирую данные в местоположение, указанное в качестве входного параметра. Это очень важно, так как локальные переменные не будут существовать после того, как вы вернетесь (хотя вы можете объявить их static
, но не давайте учить вас вредным привычкам. Что если функция будет вызвана снова…)
Ответ 2
Вот способ сделать то, что вы хотите, чтобы не сломаться, если вы находитесь в системе с другим endianness от того, на котором вы находитесь Сейчас:
byte* floatToByteArray(float f) {
byte* ret = malloc(4 * sizeof(byte));
unsigned int asInt = *((int*)&f);
int i;
for (i = 0; i < 4; i++) {
ret[i] = (asInt >> 8 * i) & 0xFF;
}
return ret;
}
Вы можете увидеть это в действии здесь: http://ideone.com/umY1bB
Проблема с приведенными выше ответами заключается в том, что они полагаются на базовое представление float
s: C не гарантирует, что самый старший байт будет "первым" в памяти. Стандарт позволяет базовой системе реализовать float
, но это похоже на то, что если вы проверите свой код на системе с определенным типом соответствия (порядок байтов для числовых типов в памяти), он перестанет работать в зависимости от вида процессора, на котором вы его запускаете.
Это действительно неприятная, труднодоступная ошибка, и вам следует избегать ее, если это вообще возможно.
Ответ 3
Я бы рекомендовал попробовать "союз".
Посмотрите на это сообщение:
http://forum.arduino.cc/index.php?topic=158911.0
typedef union I2C_Packet_t{
sensorData_t sensor;
byte I2CPacket[sizeof(sensorData_t)];
};
В вашем случае что-то вроде:
union {
float float_variable;
char bytes_array[4];
} my_union;
my_union.float_variable = 1.11;
Ответ 4
Еще один способ, без союзов:
(Предполагая, что byte = unsigned char)
void floatToByte(byte* bytes, float f){
int length = sizeof(float);
for(int i = 0; i < length; i++){
bytes[i] = ((byte*)&f)[i];
}
}
Ответ 5
Хотя другие ответы показывают, как это сделать с помощью объединения, вы можете использовать его для реализации функции, которую вы хотите:
byte[] float2Bytes(float val)
{
my_union *u = malloc(sizeof(my_union));
u->float_variable = val;
return u->bytes_array;
}
или
void float2Bytes(byte* bytes_array, float val)
{
my_union u;
u.float_variable = val;
memcpy(bytes_array, u.bytes_array, 4);
}
Ответ 6
похоже, что это работает и
#include <stddef.h>
#include <stdint.h>
#include <string.h>
float fval = 1.11;
size_t siz;
siz = sizeof(float);
uint8_t ures[siz];
memcpy (&ures, &fval, siz);
затем
float utof;
memcpy (&utof, &ures, siz);
также для двойного
double dval = 1.11;
siz = sizeof(double);
uint8_t ures[siz];
memcpy (&ures, &dval, siz);
затем
double utod;
memcpy (&utod, &ures, siz);