3
#include <stdio.h>

void main()

{

    int k = m();

    printf("%d", k);

}

void m()

{

    printf("hello");

}  

Output
hello5

What is the void function returning here? If there is no printf() then the output is 1. What is happening here?

Pankaj Mahato
  • 1,051
  • 5
  • 14
  • 26
  • Which compiler are you using? – anatolyg Feb 02 '14 at 17:50
  • http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c – Grijesh Chauhan Feb 02 '14 at 17:58
  • 2
    Until you are substantially more skilled at C and know when it is inappropriate, *always* invoke GCC with its `-Wall` option. That means "enable all of the warnings that should be on by default but, for compatibility's sake, aren't." (There are even more warnings available if you want them, but they have much higher false-positive rates.) – zwol Feb 02 '14 at 18:00

5 Answers5

7

A void function does not return anything. Your program invokes undefined behavior because it implicitly defines m to have return type int (in C89, if a function is called before it is declared, it's implicitly assumed to have return type int), but then defines it with return type void.

If you add a forward-declaration for m, the compiler will correctly complain that you're trying to use the return value of a void function, which is not possible.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 4
    What's actually happening (although there's no guarantee of consistency) is that `main` is getting the return value left behind by `printf` (which is 5 because it printed 5 characters). – hobbs Feb 02 '14 at 17:53
4

In both cases (void m with caller expecting int, void main with caller-in-C-library expecting int), this is undefined behavior, and your compiler should have chewed you out, e.g. [GCC 4.8 with -Wall]:

test.c:3:6: warning: return type of ‘main’ is not ‘int’
 void main()
      ^
test.c: In function ‘main’:
test.c:7:5: warning: implicit declaration of function ‘m’
     int k = m();
     ^
test.c: At top level:
test.c:13:6: warning: conflicting types for ‘m’
 void m()
      ^
test.c:7:13: note: previous implicit declaration of ‘m’ was here
     int k = m();
             ^

"Implicit declarations" exist only for backward compatibility with pre-C1989 programs, which are more than 20 years out of date at this point. If you had written this code in a more modern style you would've gotten a hard error:

#include <stdio.h>

extern void m(void);

int main(void)
{
    int k = m();
    printf("%d", k);
    return 0;
}

void m(void)
{
    printf("hello");
}

test.c: In function ‘main’:
test.c:7:13: error: void value not ignored as it ought to be
     int k = m();
             ^

The key addition is the extern void m(void); line. The compiler isn't allowed to look ahead to the definition of m when it checks main for errors, so you need a forward declaration to tell it what m's type really is. You should also know that in C (but not C++), void m() means "m takes an unspecified number of arguments". To declare a function taking no arguments, which is what you wanted, you have to write void m(void).

I believe what is happening on your specific system is that the return value of printf, which your code officially ignores, is being left in the return-value register and thus interpreted as the return value of m, but you cannot rely on anything predictable happening. That is what 'undefined behavior' means.

zwol
  • 135,547
  • 38
  • 252
  • 361
2

This is undefined behavior.

The reason the compiler lets you do the assignment is that there is no prototype of m available to it. When this happens, C standard says that the function must return int. Since in this case the actual function return type is void, the behavior is undefined. The value that you get in variable k is entirely arbitrary.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

The return value of a function usually stored in the one of the CPU registers, EAX for x86. As C it just a friendly assembler, you can always read the value from the register. And you will get whatever was there. Efficiently, int k = m() tells program to store value of register EAX in the variable k.

kofemann
  • 4,217
  • 1
  • 34
  • 39
0

You have not declared void m(); before calling it in main.

Some compilers assume the return type of unknown function symbols as int (unknown at the time of compilation of course) . In fact, your compiler has probably issued a compilation warning on this.

If you declare this function before main (where it should be declared), then you will probably get a compilation error.

barak manos
  • 29,648
  • 10
  • 62
  • 114