Tom
Tom

Reputation: 7921

How to convert a float literal to an unsigned int of the same bit pattern

In a header outside of my control, there is this:

typedef union {
    char * v_charp;
    int v_int;
    float v_float;
} value_t;

typedef struct var {
    char *name;
    value_t value;
} variable;

#define VARIABLE_DEF(Name, Value) {Name, {(char*)Value}}

They expect that in my code I'll do something like this:

variable my_variables[2] = {
    VARIABLE_DEF("Variable 1", 1),
    VARIABLE_DEF("Variable 2", 2)
};

Whoever wrote this apparently didn't consider that you might want to initialise the union with a floating-point literal. So I need to figure out how to convert a literal float to an integer of the same bit-pattern. If I could use an intermediate variable then it'd be easy:

float tmp;

variable my_variables[2] = {
    VARIABLE_DEF("Variable 1", tmp = 1.1f, *((unsigned int *)(&tmp))),
    VARIABLE_DEF("Variable 2", tmp = 2.2f, *((unsigned int *)(&tmp)))
};

But you can't use variables in struct initialisers. What else can I do?

Upvotes: 1

Views: 810

Answers (4)

Stephen Canon
Stephen Canon

Reputation: 106117

Used named initializers:

variable my_variables[2] = {
    VARIABLE_DEF("Variable 1", 1),
    { .name = "Variable 2", .value.v_float = 1.1f }
};

Upvotes: 0

J. C. Salomon
J. C. Salomon

Reputation: 4313

How about

variable my_variables[2] = {
    VARIABLE_DEF("Variable 1", ((value_t){.v_float = 1.1f}.v_int)),
    VARIABLE_DEF("Variable 2", ((value_t){.v_float = 2.2f}.v_int)),
};

(Untested)

On second thought, how about defining a more flexible alternative to VARIABLE_DEF and using that when needed?

Something like

#define VARIABLE_DEF_ALT(Name, Value) {Name, {Value}}
#define VARIABLE_DEF_ALT2(Name, Field, Value) {Name, {.Field = Value}}

variable my_variables[2] = {
    VARIABLE_DEF_ALT("Variable 1", .v_float = 1.1f),
    VARIABLE_DEF_ALT2("Variable 2", v_float, 2.2f),
};

should work.

Or just skip the macro:

variable my_variables[2] = {
    {"Variable 1", {.v_float = 1.1f}},
    {"Variable 2", {.v_float = 2.2f}},
};

— is that actually the macro, or are you simplifying a much more complicated case for this discussion?

Upvotes: 2

rodrigo
rodrigo

Reputation: 98338

You cannot use a function like that from Michael Kerlin's answer in the code, because function call cannot be used in initializers.

But you can write a program that does such a conversion and then copy/paste the resulting integer value into your program! (with a nice comment saying what value it really is).

Upvotes: 0

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143061

Maybe a function like static int f(float x) { return *(int*)&x; } would do?

Upvotes: 0

Related Questions