14

I thought the difference is that declaration doesn't have parameter types...

Why does this work:

int fuc();

int fuc(int i) {
  printf("%d", i);
  return 0;
}

but this fails compiling:

int fuc();

int fuc(float f) {
  printf("%f", f);
  return 0;
}

with the message:

error: conflicting types for ‘fuc’. note: an argument type that has a default promotion can’t match an empty parameter name list declaration

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
compiler
  • 4,143
  • 9
  • 36
  • 40

3 Answers3

29

A declaration:

int f();

...tells the compiler that some identifier (f, in this case) names a function, and tells it the return type of the function -- but does not specify the number or type(s) of parameter(s) that function is intended to receive.

A prototype:

int f(int, char);

...is otherwise similar, but also specifies the number/type of parameter(s) the function is intended to receive. If it takes no parameter, you use something like int f(void) to specify that (since leaving the parentheses empty is a declaration). A new-style function definition:

int f(int a, char b) { 
    // do stuff here...
}

...also acts as a prototype.

Without a prototype in scope, the compiler applies default promotions to arguments before calling the function. This means that any char or short is promoted to int, and any float is promoted to double. Therefore, if you declare (rather than prototype) a function, you do not want to specify any char, short or float parameter -- calling such a thing would/will give undefined behavior. With default flags, the compiler may well reject the code, since there's basically no way to use it correctly. You might be able to find some set of compiler flags that would get it to accept the code but it would be pretty pointless, since you can't use it anyway...

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Interesting, I didn't know of these promotions before. Apparently C has something called _the default argument promotions_ (C99 6.5.2.2.6). There is so much hidden weirdness in the C language! I wonder why they added this incredibly ugly "patch" to the standard rather than enforcing prototypes. Anyway, "future language extensions" by the C working group suggest that all of this crap will be removed from the standard, if they ever make a new version of it. – Lundin Mar 30 '11 at 06:57
  • 1
    They kept default promotions pretty much out of necessity: prototypes were a new invention during the original C standardization. Requiring prototypes would have broken essentially 100% of existing code and compilers... – Jerry Coffin Mar 30 '11 at 12:59
  • The way you put it seems to suggest a prototype is not a declaration (without argument types -> declaration, with argument types -> prototype). – undur_gongor May 11 '15 at 08:37
  • @undur_gongor: Well, a prototype does also declare the function, of course, but yes, it sounds like you've understood the distinction I was trying to make. – Jerry Coffin May 11 '15 at 14:06
0

prototype = forward declaration, so you can use it before you tell the compiler what it does. It still has parameters, however.

Useful in a lot of respects!

ultifinitus
  • 1,813
  • 2
  • 19
  • 32
  • 1
    If `prototype = forward declaration`,then what's the difference between `forward declaration` and `declaration`?? – compiler Mar 30 '11 at 03:42
  • The forward declaration comes before the actual declaration. forward declaration = void hi(); declaration = void hi(){ printf("hi"); } – ultifinitus Mar 30 '11 at 03:44
0

The declaration int fuc(float); tells the compiler that there exists a function fuc which takes a float and returns an int.

The definition int fuc(float f) { /*...*/ } tells the compiler what fuc actually is and also provides the declaration as well.

The difference between a declaration and definition is the difference between saying that a size 6 blue hat exists and and handing someone a size 6 blue hat: the declaration says that there is such a thing, the definition says that this thing right here is the thing in question.

mu is too short
  • 426,620
  • 70
  • 833
  • 800