views:

95

answers:

1

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.
+7  A: 

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
};
caf
Oops, I forgot to mention the standard I'm following in the Q. Updated to mention: GNU99.
detly
@detly: Then the above should work fine - no need for the python script at all..
caf
caf is right that this compiles and works with gnu99, I just tried it out. Did you mean gnu89? Or do you absolutely need an array of ints?
ryan_s
Neither, I just haven't had a chance to try it out yet :)
detly
caf's solution looks good. Note something like `#define COMPILE_TIME_CONVERT(x) ((IntFloat)(float)(x)).intval` does **not** work within your original DEFAULTS[] with gcc.
Joseph Quinsey
This works perfectly, thanks :) Is this a C99 feature, or a GNU extension? It'd be good to know so I can document it.
detly
@detly: It's standard C99.
caf