简体   繁体   中英

Function definition in Macros in C

This code throws out an error saying that "code undelcared."

#include<stdio.h>
#define MAIN() c##o##d##e
int main()
{
    MAIN();
    printf("C program");
    return 0;
}
int code()
{
    printf("C is life");
}

Whereas, this code runs smoothly.

#include<stdio.h>
#define MAIN() m##a##i##n
int main()
{
    MAIN();
    printf("C program");
    return 0;
}
int code()
{
    printf("C is life");
}

Output:

C program

This code also runs smoothly.

#include <stdio.h>
#define macro(n, a, i, m) m##a##i##n
#define MAIN macro(n, a, i, m)

int MAIN()
{
    printf("C is life");
    return 0;
}

Output:

C is life

In the first code, why doesn't the code work as like main? I don't know what is the process after the concatenation 'main' is completed by the macro. Kindly explain the process behind these codes, in simple terms. Thanks in advance.

I also tried by defining the code function.

#include<stdio.h>
#define MAIN() c##o##d##e
int code(void);
int main()
{
    MAIN();
    printf("C program");
    return 0;
}
int code(void)
{
    printf("C is life\n");
    return 0;
}

Output:

C program

So, defining a function should not be the problem. My question is, what happens after concatenation? Thanks in advance.

In C, you have to define the prototype of your function int code () before any calls :

int code (void);

The function main is declared in assembly code, this is why your second version compiles et runs correctly.

If you want to avoid this error please add -Wmissing-prototypes compilation flag in order to let the compiler checks for you if your function has a prototype.

The problem is that code() function is not yet declared when main() is compiled.

Either move code() before main() :

#include<stdio.h>
#define MAIN() c##o##d##e
int code()
{
    printf("C is life");
}
int main()
{
    MAIN();
    printf("C program");
    return 0;
}

Or forward declare code() :

#include<stdio.h>
#define MAIN() c##o##d##e

int code();

int main()
{
    MAIN();
    printf("C program");
    return 0;
}
int code()
{
    printf("C is life");
}

In C (since the C99 standard) you need to declare all functions before you use them.

In the first example you haven't declared the code function before you attempt to use it. You solve it by adding a function prototype :

// Declare the function, also known as a function prototype
void code(void);

int main(void)
{
    // ...
}

// Define the function
void code(void)
{
    // ...
}

The second example works because you use main which is already declared at that point. If a function haven't been declared before, the definition also declares the function.

Also note that your macro after expansion doesn't actually call the code (or the main ) function. This is good, since calling main recursively (directly or indirectly) is generally bad.

Just remember macros are replaced at preprocessor stage itself. In C , every function needs to be prototyped before using/calling it so that compiler knows in advance about it's arguments and return type to avoid conflicts.

Case 1 :- when below code blocks executes, macro name MAIN() got replaced with code .

#define MAIN() c##o##d##e
int main(){
        MAIN();
        printf("C program");
        return 0;
}
int code(){
        printf("C is life");
}

And it looks like below after pre-processor stage

int main(){
 code; /* errorenous statement */
 printf("C program");
 return 0;
}
int code(){
 printf("C is life");
}

observe the line code; in above code block, it cause the compilation error . When you run above code like gcc -Wall -Wstrict-prototypes -Werror test.c where it will convert warning into error .

error: 'code' undeclared (first use in this function) #define MAIN() c##o##d##e ^

to solve this, declare the code() like before #define

int code(void); /* declaration */

There is one more warning converted into error

error: statement with no effect [-Werror=unused-value] #define MAIN() c##o##d##e

Because after macro replacement it looks like code; and here compiler rightly complaining above statement with no effect . So to avoid this change the macro name from MAIN() to MAIN . for eg

#define MAIN c##o##d##e

Correct version of case-1 code

#include<stdio.h>
int code(void);
#define MAIN c##o##d##e
int main(void){
        MAIN();
        printf("C program");
        return 0;
}
int code(void){
        printf("C is life");
        return 0;
}

And it produces output as

C is lifeC program

Case 2 :- when below code executes, macro name MAIN() gets replaced with main

#define MAIN() m##a##i##n
int main(){
    MAIN();
    printf("C program");
    return 0;
}
int code(){
    printf("C is life");
}

And it looks like at preprocessor stage

int main(){
    main; /* it causes error */
    printf("C program");
    return 0;
}
int code(){
    printf("C is life");
}

Case 3 :- when below code blocks executes, macro name MAIN() got replaced with code & here you declared the code() also.

#define MAIN() c##o##d##e
int code(void);
int main() {
    MAIN();
    printf("C program");
    return 0;
}
int code(void) {
    printf("C is life\n");
    return 0;
}

And it looks like below after pre-processor stage

int code(void);
int main() {
 code;/* error causing statement */
 printf("C program");
 return 0;
}
int code(void) {
 printf("C is life\n");
 return 0;
}

Suggest you to compile any C code with

gcc -Wall -Wstrict-prototypes -Werror test.c

so by converting warning to error you will learn more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM