Подтвердить что ты не робот

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!

4b9b3361

Ответ 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);