C++ Union of a Float and a Byte Array Issue

不羁的心 提交于 2019-12-14 01:29:02

问题


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. I have to convert the float to a byte array to interact with 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? Also if anyone has a better way of doing this, I am open to suggestions. Thanks in advance


回答1:


Reading not the "active" field of the union is UB (Undefined Behavior).

You have to use 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;
}



回答2:


Arduino provides .put() and .get() methods with EEPROM object so you don't have to reinvent the wheel. 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()

This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change.




回答3:


It is common problem for struct and union. You need investigate "aligns". Default it usually "word" (2 bytes) so your byte byteVal[4]; can take 8 bytes (byte, empty, byte, empty ...). You must use __attribute__ ((packed)) for avoid it.



来源:https://stackoverflow.com/questions/52122263/c-union-of-a-float-and-a-byte-array-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!