Определение функции в макросах на С - PullRequest
0 голосов
/ 11 июня 2018

Этот код выдает ошибку, говорящую, что «код недопустим».

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

Принимая во внимание, что этот код работает гладко.

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

Вывод:

C program

Этот код также работает гладко.

#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;
}

Вывод:

C is life

В первом коде, почему код не работает как main?Я не знаю, каков процесс после завершения макрокоманды 'main'.Пожалуйста, объясните процесс, стоящий за этими кодами, в простых терминах.Заранее спасибо.

Я также пытался определить функцию кода.

#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;
}

Вывод:

C program

Таким образом, определение функции не должно быть проблемой.Мой вопрос: что происходит после объединения?Заранее спасибо.

Ответы [ 4 ]

0 голосов
/ 11 июня 2018

Только помните, macros заменяются на самой preprocessor стадии.В C каждая функция должна быть прототипирована перед использованием / вызовом, чтобы компилятор заранее знал о ее arguments и return type, чтобы избежать конфликтов.

Случай 1: - когда выполняются нижеследующие кодовые блоки, имя макроса MAIN() заменяется на code.

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

И это выглядит ниже после препроцессора stage

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

соблюдайте строку code; в приведенном выше блоке кода, это вызывает ошибку компиляции .Когда вы запускаете код выше gcc -Wall -Wstrict-prototypes -Werror test.c, где он преобразует warning в error.

ошибка: «код» необъявлен (первое использование в этой функции) #define MAIN () c ##o ## d ## e ^

, чтобы решить эту проблему, объявите code() как прежде #define

int code(void); /* declaration */

Есть еще одно предупреждение, преобразованное в ошибку

ошибка: оператор без эффекта [-Werror = unused-value] #define MAIN () c ## o ## d ## e

Поскольку после замены макроса это выглядит как code; и здесь компилятор справедливо жаловался на заявление без эффекта .Поэтому, чтобы избежать этого, измените имя макроса с MAIN() на MAIN.например,

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

Правильная версия кода case-1

#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;
}

И он производит вывод как

C is lifeC program

Случай 2: - при выполнении приведенного ниже кода имя макроса MAIN() заменяется на main

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

И это выглядит на этапе препроцессора

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

Случай 3: - при выполнении нижеприведенных блоков кода имя макроса MAIN() было заменено на code, и здесь вы также объявили code().

#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;
}

И это выглядит ниже после стадии препроцессора

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

Предложите вам скомпилировать любой код C с помощью

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

, поэтому, преобразовав предупреждение в ошибку, вы узнаете больше.

0 голосов
/ 11 июня 2018

Проблема в том, что функция code() еще не объявлена ​​при компиляции main().

Либо двигаться code() до main():

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

Или объявить вперед 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");
}
0 голосов
/ 11 июня 2018

В C (начиная со стандарта C99) вам необходимо объявить все функции перед их использованием.

В первом примере вы не объявили функцию code перед тем, как пытаться ее использовать.Вы решаете это, добавляя прототип функции :

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

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

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

Второй пример работает, потому что вы используете main, который уже объявлен в тот момент.Если функция не была объявлена ​​ранее, определение также объявляет функцию.

Также обратите внимание, что ваш макрос после раскрытия на самом деле не вызывает code (или main) функция.Это хорошо, поскольку рекурсивный (прямой или косвенный) вызов main, как правило, плох.

0 голосов
/ 11 июня 2018

В C вы должны определить прототип вашей функции int code () перед любыми вызовами:

int code (void);

Функция main объявлена ​​в коде сборки, поэтому ваша вторая версия компилирует etработает правильно.

Если вы хотите избежать этой ошибки, добавьте флаг компиляции -Wmissing-prototypes, чтобы компилятор проверил вас, есть ли у вашей функции прототип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...