3

I have the following code in my program:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int print_numbers_above(double x, float y, int z)
{
    printf("x=%lf, y=%f, z=%d\n", x, y, z);
}
int main()
{
    double x = 1.25;
    float y = 1.25;
    int z = 3;
    print_numbers_below(x, y, z);
    print_numbers_above(x, y, z);
    return 0;
}
int print_numbers_below(double x, float y, int z)
{
    printf("x=%lf, y=%f, z=%d\n", x, y, z);
}

Output:

x=1.25, y=0.000000, z=Garbage

x=1.250000, y=1.250000, z=3

Now, I know that the function print_numbers_below() should have been declared earlier (or should have been defined before main). But it doesn't throw an error. It assumes it to be an extern function (and since it is returning int, there isn't any conflict of return types). Now, I fail to understand why can't I pass more than 1 argument correctly?

(I'm using Visual Studio 2013)

user2684198
  • 812
  • 1
  • 10
  • 18
  • 1
    "%lf" ? That's for a `long double` – nos Mar 01 '14 at 02:05
  • Run the compilation with /ANALYSIS given on the compiler's command line :) – Kuba hasn't forgotten Monica Mar 01 '14 at 02:18
  • @nos Wrong. %lf and %f do exactly the same thing in a printf format. – Jim Balter Mar 01 '14 at 02:35
  • "But it doesn't throw an error." -- Then your compiler is broken. Try at least to bump up the warning level, and even tell it that warnings are errors. – Jim Balter Mar 01 '14 at 02:42
  • 1
    @nos P.S. The format for long double is %Lf, not %lf ... please do not post incorrect information. Before "correcting" someone's code, please verify that it's really wrong and that you have it right. The same goes for people upvoting erroneous comments. – Jim Balter Mar 01 '14 at 02:48

2 Answers2

6

A reasonable compiler would give you the following error:

foo.c:12:5: warning: implicit declaration of function 'print_numbers_below' is invalid in C99 [-Wimplicit-function-declaration]
    print_numbers_below(x, y, z);
    ^
foo.c:16:5: error: conflicting types for 'print_numbers_below'
int print_numbers_below(double x, float y, int z)
    ^
foo.c:12:5: note: previous implicit declaration is here
    print_numbers_below(x, y, z);
    ^
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • I don't feel that this answer is really helpful without explaining why and how the types are conflicting. – sepp2k Mar 01 '14 at 13:11
3

When you call a function the compiler hasn't seen a prototype for, it applies the default argument promotions to all arguments. Chars and shorts are promoted to ints, and floats are promoted to doubles. This breaks when print_numbers_below actually wants a float.

If you haven't defined the function yet, always use a prototype.

Community
  • 1
  • 1
user2357112
  • 260,549
  • 28
  • 431
  • 505