2

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?

TallTed
  • 9,069
  • 2
  • 22
  • 37
Karim Stekelenburg
  • 633
  • 12
  • 26

4 Answers4

8

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.

PC Luddite
  • 5,883
  • 6
  • 23
  • 39
4

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.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

You have to use the & operator. For example replace scanf("%f", v); with scanf("%f", &v);. This will pass the address of the variable (instead of the value) to scanf().

splotz90
  • 321
  • 2
  • 11
2

You have to write scanf("%f", &i); e.t.c, as you want the variable to be passed as a pointer as C has no reference type like C++

Joe
  • 31
  • 3