user3314691
user3314691

Reputation: 115

'C' - How to initialise a 32 bit integer value with a 32 bit float value?

I am trying to find a general purpose way to initialise an array or structure with parameter values. When the parameters are consumed from the array or structure the context will be known by my function and so it will know how to use the values correctly.

To initialise the array/structure I was wanting to do something like this:

const void *para[] = {  // General Purpose store for parameters
    "1234",             // Store string pointer
    (void *)1234,       // Store integer value
    (void *)12.34f,     // Store float value
};

The string and integer parameter types are ok. The float does not work because the compiler has no method to cast a float to a void pointer.

What I need is a way to cast a float value to its binary representation so it can treated like a 32 bit unsigned integer. Can this be done ?

I could solve this problem with the brute force of memcpy() but this would require the 'const' to be removed. The ultimate aim is that the code will be ported to a embedded ARM system with limited SRAM so the array/structure needs to located in ROM and so needs to be initialised by the compiler and not at run time.

Upvotes: 0

Views: 644

Answers (2)

Christian T
Christian T

Reputation: 56

Your generic data array contains void pointer. A pointer to a non defined data type. On many systems pointers to most datatypes do not vary in size so it does not matter what it points to. This would only become relevant when doing pointer arithmetic or accessing the content. You may know this. As you told, your code later on "knows" in what context to use which pointer. So far so good. Let's assume we have a 32bit systems as it matches your data types.

Now to your types:

  • The string "1234" ist stored in the text section during compile time. And your compiler fills your data array with the pointer to that memory section.
  • With the integer you explicitly cast 1234 to a void pointer, telling the compiler: "Hey, this is a pointer, not an integer". This works as long as your integer and your pointer have the same length or the pointer is bigger. So on our 32bit it's ok. So you store the value directly in the field where you would normally store a pointer to something.
  • With the float the mechanism from above does not work. A float can never be interpreted as a memory address so the compiler fails.

Two options: First, store int and float in text/constant section and just put the pointer in my array. But we have to store these values beforehand... (or maybe there's a fancy trick). This will work for any type!:

static int v1 = 1234;
static float v2 = 12.34f;

const void *para[] = {  // General Purpose store for parameters
    "1234",             // Store string pointer
    &v1,                // Store integer value
    &v2,                // Store float value
};

Second and the way i would prefere here is using a union.

union data_storage {
     const int t_int;
     const float t_float;
     const char *t_string;
};

const union data_storage params[] = {  // General Purpose store for parameters
    {.t_string = "1234"},           // Store string pointer
    {.t_int = 1234},                // Store integer value
    {.t_float = 12.34f},            // Store float value
};

I tested it with

fprintf(stdout, "%s\n%i\n%f\n", params[0].t_string, params[1].t_int, params[2].t_float);

Upvotes: 1

n. m. could be an AI
n. m. could be an AI

Reputation: 119877

Use a structure and not an array.

struct s_para { const char* a; int b; float c; } const para 
    = { "1234", 1234, 12.34f };

No need to cast anything.

Upvotes: 4

Related Questions