Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Float seen as a double

Tags:

c

When running this little C script using Xcode, I get this message:

Format specifies type 'float *' but the argument has type 'double" at scanf("%f", v) and scanf("%f", i).

I don't get it, since I have not declared any double type variables.

int main(int argc, const char * argv[]) {
    char choice[10];

    float v;
    float i;
    float r;

    printf("What would you like to calculate?: ");
    scanf("%s", choice);
    printf("\nYou chose: \n""%s", choice);

    if (strcmp(choice, "r") == 0)
    { 
        printf("\nPlease enter voltage (V): \n");
        scanf("%f", v);

        printf("\nPlease enter current (I): \n");
        scanf("%f", i);

        r = v/i;

        printf("%f", r);
    }
}

Any ideas?

like image 971
Karim Stekelenburg Avatar asked Dec 04 '25 18:12

Karim Stekelenburg


2 Answers

You're getting that warning because you failed to pass a pointer to a float (float*) to the function scanf. The compiler tells you that it's a double because scanf is a variadic function. Variadic parameters are subject to default argument promotion (the gist of which means that arguments of certain data types are converted to larger data types when they are passed to the function. E.g. float in this case is promoted to double).

The only way for a function in C to modify variables v, i, and choice is to pass them as pointers, so you need to pass pointers to scanf, using the & "address of" operator.

Your code should look like this:

int main(int argc, const char * argv[]) {
    char choice[10];

    float v;
    float i;
    float r;

    printf("What would you like to calculate?: ");
    scanf("%9s", &choice); /* this specifier prevents overruns */
    printf("\nYou chose: \n""%s", choice);

    if (strcmp(choice, "r") == 0)
    { 
        printf("\nPlease enter voltage (V): \n");
        scanf("%f", &v); /* use a pointer to the original memory */

        printf("\nPlease enter current (I): \n");
        scanf("%f", &i); /* use a pointer to the original memory */

        r = v/i;

        printf("%f", r);
    }
}

Note also that I used the format specifier %9s. That way, if the user inputs more than 9 characters, adjacent memory won't be overwritten. You have to reserve the last element of the array for the null character \0 because strings in C end with \0.

like image 122
PC Luddite Avatar answered Dec 06 '25 08:12

PC Luddite


I don't get it since I have not declared any double type variables.

When there is no visible prototype to indicate what type a function expects for a given argument, or when that argument is among a set of variadic arguments, then default argument promotion is performed on that argument. This provides for compatibility with pre-ANSI C code that assumed such promotions were performed on all arguments.

In this case, scanf() is variadic, with this prototype:

int scanf(const char *fmt, ...);

so everything but the format is subject to default argument promotion. For arguments of type float, that is a promotion to double, and that's where your double comes from.

Of course, as other answers describe, you shouldn't be passing the float at all, but rather a pointer to it.

like image 39
John Bollinger Avatar answered Dec 06 '25 09:12

John Bollinger