Jhansi Rani
Jhansi Rani

Reputation: 449

Scope of a function when defined within another function

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

Answers (6)

Lundin
Lundin

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

Vlad from Moscow
Vlad from Moscow

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

mafso
mafso

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

Gyapti Jain
Gyapti Jain

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

Gopi
Gopi

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

DomDom
DomDom

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

Related Questions