4

I found this question on an online exam. This is the code:

#include <stdio.h>

int main(void) {
    int demo();
    demo();
    (*demo)();
    return 0;
}

int demo(){
    printf("Morning");
}

I saw the answer after the test. This is the answer:

MorningMorning

I read the explanation, but can't understand why this is the answer. I mean, shouldn't the line int demo(); cause any "problem"?

Any explanation is helpful. Thanks.

Debanik Dawn
  • 797
  • 5
  • 28

4 Answers4

5

It is not a problem because that int demo(); is not a function definition, it is just an external declaration, saying (declaring) that a function of such name exists.

In C you cannot define a nested function:

int main(void) {
    int demo() {} //Error: nested function!!!
}

But you can declare a function just fine. It is actually equivalent to:

#include <stdio.h>

int demo(); //function declaration, not definition

int main(void) {
    demo();
    (*demo)();
    return 0;
}

int demo(){
    printf("Morning");
}

except that in your code the external forward demo() declaration is only visible inside main.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • what's going to happen if I don't "declare" the function? I mean, I removed the line `int demo();` and it still works fine. – Debanik Dawn Jul 10 '18 at 08:59
  • 4
    @DebanikDawn: Ah, that's because in C there is that infamous _automatic function declaration_, that in case you use a function without a previous declaration, the compiler will create one for you, taking whatever arguments you are passing and returning `int`... handy, maybe in the 1970s, but very dangerous. Turn on your compiler warnings and you'll see the danger (and keep them on!). – rodrigo Jul 10 '18 at 09:01
  • Thanks, that was helpful. :) – Debanik Dawn Jul 10 '18 at 09:08
4

You can declare a function inside another function. This is allowed. The only thing is it is visible only inside the function in which it is declared.

H.S.
  • 11,654
  • 2
  • 15
  • 32
2

Other answers didn't explain the

(*demo)();

part. Here's a partial explanation:

demo (without parentheses) is the function pointer. So you can first dereference it to get a function then call it with parentheses (wrapping the dereferenced object into parentheses else it means that you want to dereference the return value of the function)

So it's strictly equivalent to

demo();

(the notation is useful when the function pointer is stored in a variable, here it's just more cryptic than necessary)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • If `demo()` is same as `(*demo)()`, doesn't that imply `demo` and `*demo` is the exact same thing? How can that be? – Debanik Dawn Jul 10 '18 at 14:00
  • P.S. I wrote a program in which I created a function `hello()` and then in the main function printed the values of `hello` and `*hello` and `&hello`. They are exactly the same, I don't get it. – Debanik Dawn Jul 10 '18 at 14:03
  • ìt's just a question of notation. `hello` is the address of the routine. It's not like a normal variable. Getting the address of the address or dereferencing it has no effect. – Jean-François Fabre Jul 10 '18 at 14:11
  • Ah, okay. I understand now. Thanks. – Debanik Dawn Jul 10 '18 at 14:32
0

int main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ } is equivalent to int main(void) { extern int demo(); /*...*/ }; int demo(){ /*...*/ } It declares the demo function with external linkage, inside the main function. The demo identifier will be valid till the end of the scope, but demo will be a normal, external function.

Unfortunately, you cannot do this for functions that are static, because the standard (http://port70.net/~nsz/c/c11/n1570.html#note30) makes things like int main(void) { static int demo(); } static int demo(){ /*...*/ } illegal.

As to why (*demo)(); works and is in this context equivalent to demo(); or (&demo)(); or (*&demo)();:

After you declare demo with int demo();, demo is a function designator (which is not the same as a function pointer, not unlike an array designator is not the same as a pointer the the array's first element). Like arrays, though, function designators almost always decay to function pointers (see 6.3.2.1p4) and this type of decay happens in function calls too. Essentially demo(); decays demo to a pointer and then calls the function pointer. Applying * to such a pointer yields again the function designator which again decays to a pointer to make the call.

Admittedly, all this stuff is very weird and esoteric and I can't even think of a situation where the distinction is useful. IMHO, it's probably best to stick to demo(); or (demo)() (if you want to supress macro expansion) and never use (*demo)() (at least not on functions -- on function pointers it is at least somewhat informative) and especially not (&demo)() as it serves little purpose other than to confuse the reader.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142