Search code examples
cfloating-pointtype-conversionintegerfunction-definition

Cast function argument passed by rereference in C


I have the following function. It works with short:

void foo (short n, short * res)
{
  *res = n*2;
}

I want to store the result in double variable. For example:

short in = 5;
double out = 0;
foo(in,&out);

But in that way the result is some garbage. Is there a way to cast these types in such situation, or the only solution is to use some temp variable of type short?


Solution

  • If you cannot change the function, then I would do something like this:

    short in = 5;
    short tmp;
    double out;
    foo(in,&tmp);
    out = tmp;
    

    If you do this a lot, consider writing a wrapper as @einpoklum did in his answer like this:

    void foo_wrapper(short n, double *out)
    {
        short tmp;
        foo(n, &tmp);
        out = tmp;
    }
    

    I guess it could theoretically be possible with casting, but I would advice against it. The risks of doing it wrong is high, and you might get hard chased bugs, and if you do explicit casts, the compiler will not give you warnings. I wrote a rant about casting in this answer

    In this particular case, note that the function foo have no idea of the resulting type. So you will need a temporary variable. You could get rid of that by using the out variable as it's own temporary variable with some casting but I strongly advice against it!

    short in = 5;
    double out;
    foo(in, (short*)&out);
    out = *(short*)&out; // Evil! Avoid code like this!
    printf("%f\n", out);
    

    This works on my machine, but it does violate aliasing rules as @chqrlie wrote in comments. Do NOT do like this!

    @chqrlie also wrote an alternative approach with no extra variable and no evil casting. It works, but UGH! Don't do like this either:

    short in = 5; 
    foo(in, &in); // No! Just don't!
    out = in;     
    

    Of course it will not work if you need the original value, but that's pretty obvious. The major flaw here is that it's just plain bad. Don't reuse variables for different purposes just to get rid of a temporary variable.