Reputation: 449
What will happen when a function defined within another function? What is the difference between code 1 and code 2?
CODE 1:
#include<stdio.h>
void m();
void main()
{
m();
void m()
{
printf("hi");
}
}
CODE 2:
#include <stdio.h>
void m();
void main()
{
void m()
{
printf("hi");
}
m();
}
When I compiled code 1 in gcc compiler, I got linkage error. But when I compiled code 2, I didn't get any error. I got output "hi". I want to know how compilation is done, when we write function definition within another function. I know that when we write function definitions not within another function, wherever be the function definition, we will not get any error when we call that function. for example see the below code:
CODE 3:
#include <stdio.h>
void m();
void main()
{
m();
}
void m()
{
printf("hi");
}
In code 3,even though I called the function before definition, it didn't show any error and I got output. Why it is not happening with code 1.
Upvotes: 3
Views: 429
Reputation: 213920
You are not compiling your code as standard C. GCC is tricky because it comes with crappy non-standard settings by default. To use GCC as a proper C compiler, you must do gcc -std=c11 -pedantic-errors
, where c11 is the preferred standard (switch to c99 if you have an old version of GCC). While you are at it, ensure to enable all warnings too:
gcc -std=c99 -pedantic-errors -Wall -Wextra
Now that the compiler is configured to be a C compiler, we get the following errors:
CODE1 and CODE2:
error: return type of 'main' is not 'int' [-Wmain].
This error comes because when GCC is set to be a C compiler, it is not providing an implementation-defined way to specify main. You have to change main to int main (void)
.
error: ISO C forbids nested functions [-Wpedantic]
This error comes because nested functions aren't allowed by the C standard. You got away with it before, because you had GCC set to be a non-standard compiler.
Upvotes: -1
Reputation: 311018
Neither C nor C++ allows to define a function within another function. So it seems you are using a special language extension of compiler GCC that allows to define local functions inside another functions.
In the first program function m is declared in file scope. So its definition will be searched by the compiler in the file scope. When the function is called inside main only this file scope declaration is visible. However the compiler did not find its file scope definition so it issued an error.
In the second program there is also a declaration of function m in the file scope. However inside function main there is another declaration of function m that has block scope and hides the declaration with the file scope. Take into account that a definition also is a declaration. So the call of m refers to the function m that is declared inside main and has block scope. The compiler has the function definition and can call it.
in the third program that satisfies the C Standard inside main the call of m refers to the function m declared in the file scope and there is a definition of this function in the file scope. So there is no any problem.
Upvotes: 2
Reputation: 5543
In code 3, even though I called the function before definition, it didn't show any error and I got output. Why it is not happening with code 1?
Code 3 is conforming standard C code. A function with external linkage can be called wherever a declaration is visible (provided a definition exists somewhere in the programme, it doesn't have to be in the same file).
When I compiled code 1 in gcc compiler, I got a linkage error.
Nested functions are a GCC extension:
A nested function always has no linkage. Declaring one with extern or static is erroneous. If you need to declare the nested function before its definition, use auto (which is otherwise meaningless for function declarations).
At the point m
is called, an external declaration (the file scope declaration void m();
) is visible. As there is no external definition in this source file, gcc
assumes it is in another translation unit, and eventually the linker fails finding it. According to the quoted documentation, a valid version could be
#include <stdio.h>
int main(void)
{
auto void m(); /* Hides the outer declaration. */
m(); /* Refers to the nested function, not to an external one now. */
void m()
{
printf("hi");
}
}
But when I compiled code 2, I didn't get any error. I got output "hi".
At the point, where m
is called, the nested function is visible, hiding the file-scope declaration. The file-scope declaration (declaring a function with external linkage) is never used, so the linker doesn't try to resolve a call to it.
A conforming implementation may accept a declaration of main
as a function returning void
, but doesn't have to. Old-style (or K&R-style) declarations and definitions are obsolescent in C89, C99 and C11, so it's better to use
int main(void);
void m(void);
Upvotes: 1
Reputation: 4106
You can not define functions inside function. It is not allowed in C
and thus won't compile. Code snippet 1 and 2 are invalid and only snippet 3 is valid ANSI C
code.
Why code 1 does not compile and code 2 compiles well in gcc
Code 2 compiles under gcc because of a GNU compiler extension. You must declare the function before first usage for this extension to work.
Then why does code 3 compiles
In Snippet 3, you are declaring the function before first usage which is enough for compiler to place the required code. At linking time, required linking with the definition code is required. There is no necessity from linker about the placing of definition (In ISO C specifcations), the function definition is allowed to present even in a separate compilation unit.
Upvotes: 2
Reputation: 19864
Check the link below: Nested function in C
C doesn't support nested functions so your Code Snippet 1 and 2 are not allowed standards though you might see code snippet 2 working because you have function call after function definition.
The only allowed snippet is Code 3
the rest should not be done in C .
GCC special extensions: https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
Upvotes: 0
Reputation: 76
It's a scope problem. In your CODE 1 sample, the m function is only visible within the main function. So the function header you put before the main (void m();) expect a global m function and did not find it, that's why you have a link error. In your code 2 sample, the m function is found because it's written before the call, your global m function is still not present but not used => you don't have the link error. In your code 3 sample, your m function is global and then found as expected by the header => no error
Upvotes: 1