简体   繁体   English

C ++浮点数和字节数组的问题

[英]C++ Union of a Float and a Byte Array Issue

I am working on an arduino (based off the AVR platform) and I have a method that takes in a float and writes it to EEPROM. 我正在研究arduino(基于AVR平台),我有一个接收浮点数并将其写入EEPROM的方法。 I have to convert the float to a byte array to interact with EEPROM. 我必须将float转换为字节数组以与EEPROM交互。 I have two functions as follow: 我有两个功能如下:

void WriteFloatToEEPROM(int address, float value) {
    union {
        byte byteVal[4];
        float floatVal;
    } data;

    data.floatVal = value;

    for (int i = 0; i < 4; i++) {
        EEPROM.update(address + i, data.byteVal[i]);
    }   
}

float ReadFloatFromEEPROM(int address) {
    union {
        byte byteVal[4];
        float floatVal;
    } data;

    for (int i = 0; i < 4; i++) {
        uint8_t readValue = EEPROM.read(address + i);

        data.byteVal[i] = readValue;        
    }

    return data.floatVal;
}

When I print out the results of this I get the following as a few examples: 当我打印出结果时,我得到以下几个例子:

Read value at address 50 for float read 0
Read value at address 51 for float read 0
Read value at address 52 for float read 0
Read value at address 53 for float read 0
    Returned float val for address 50:0.00
Read value at address 90 for float read 0
Read value at address 91 for float read 0
Read value at address 92 for float read 0
Read value at address 93 for float read 160
    Returned float val for address 90:-0.00
Read value at address 130 for float read 44
Read value at address 131 for float read 113
Read value at address 132 for float read 61
Read value at address 133 for float read 138
    Returned float val for address 130:-0.00
Read value at address 170 for float read 0
Read value at address 171 for float read 0
Read value at address 172 for float read 0
Read value at address 173 for float read 0
    Returned float val for address 170:0.00

Am I using a union wrong/writing to EEPROM backwards or something? 我使用工会错误/向后写入EEPROM还是什么? Also if anyone has a better way of doing this, I am open to suggestions. 如果有人有更好的方法,我愿意接受建议。 Thanks in advance 提前致谢

Reading not the "active" field of the union is UB (Undefined Behavior). 读取不是联合的“活动”字段是UB(未定义行为)。

You have to use memcpy : 你必须使用memcpy

void WriteFloatToEEPROM(int address, float value) {
    byte byteVal[sizeof(float)];
    memcpy(byteVal, &value, sizeof(float));

    for (int i = 0; i < sizeof(float); i++) {
        EEPROM.update(address + i, byteVal[i]);
    }   
}

float ReadFloatFromEEPROM(int address) {
    byte byteVal[sizeof(float)];

    for (int i = 0; i < sizeof(float); i++) {
        byteVal[i] = EEPROM.read(address + i);
    }

    float f;
    memcpy(&f, byteVal, sizeof(float));
    return f;
}

Arduino provides .put() and .get() methods with EEPROM object so you don't have to reinvent the wheel. Arduino为EEPROM对象提供了.put().get()方法,因此您不必重新发明轮子。 Your code could be as simple as: 您的代码可以像下面这样简单:

void WriteFloatToEEPROM(int address, float value)
{
    EEPROM.put(address, value);
}

float ReadFloatFromEEPROM(int address)
{
    float value;
    EEPROM.get(address, value);
    return value;
}

.put() also acts in a similar way to .update() .put()也以类似于.update()

This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change. 此函数使用EEPROM.update()执行写操作,因此如果未更改,则不会重写该值。

It is common problem for struct and union. 这是struct和union的常见问题。 You need investigate "aligns". 你需要调查“对齐”。 Default it usually "word" (2 bytes) so your byte byteVal[4]; 默认它通常是“字”(2字节)所以你的byte byteVal[4]; can take 8 bytes ( byte, empty, byte, empty ... ). 可以占用8个字节( byte, empty, byte, empty ... )。 You must use __attribute__ ((packed)) for avoid it. 您必须使用__attribute__ ((packed))来避免它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM