Compile time float packing/punning

2019-05-14 07:35发布

I'm writing C for the PIC32MX, compiled with Microchip's PIC32 C compiler (based on GCC 3.4).

Added The standard I'm following is GNU99 (C99 with GNU extensions, compiler flag -std=gnu99)

My problem is this: I have some reprogrammable numeric data that is stored either on EEPROM or in the program flash of the chip. This means that when I want to store a float, I have to do some type punning:

typedef union
{
    int intval;
    float floatval;
} IntFloat;

unsigned int float_as_int(float fval)
{
    IntFloat intf;
    intf.floatval = fval;
    return intf.intval;
}

// Stores an int of data in whatever storage we're using
void StoreInt(unsigned int data, unsigned int address);

void StoreFPVal(float data, unsigned int address)
{
    StoreInt(float_as_int(data), address);
}

I also include default values as an array of compile time constants. For (unsigned) integer values this is trivial, I just use the integer literal. For floats, though, I have to use this Python snippet to convert them to their word representation to include them in the array:

import struct
hex(struct.unpack("I", struct.pack("f", float_value))[0])

...and so my array of defaults has these indecipherable values like:

const unsigned int DEFAULTS[] =
{
    0x00000001, // Some default integer value, 1
    0x3C83126F, // Some default float value, 0.005
}

(These actually take the form of X macro constructs, but that doesn't make a difference here.) Commenting is nice, but is there a better way? It's be great to be able to do something like:

const unsigned int DEFAULTS[] =
{
    0x00000001, // Some default integer value, 1
    COMPILE_TIME_CONVERT(0.005), // Some default float value, 0.005
}

...but I'm completely at a loss, and I don't even know if such a thing is possible.

Notes

  1. Obviously "no, it isn't possible" is an acceptable answer if true.
  2. I'm not overly concerned about portability, so implementation defined behaviour is fine, undefined behaviour is not (I have the IDB appendix sitting in front of me).
  3. As fas as I'm aware, this needs to be a compile time conversion, since DEFAULTS is in the global scope. Please correct me if I'm wrong about this.

1条回答
成全新的幸福
2楼-- · 2019-05-14 08:29

Can you make your DEFAULTS array an array of IntFloat instead?

If you can, and your compiler supports C99, then you can do this:

const IntFloat DEFAULTS[] =
{
    { .intval = 0x00000001 }, // Some default integer value, 1
    { .floatval = 0.005 }, // Some default float value, 0.005
};
查看更多
登录 后发表回答