Вызов функций из другого файла c

На самом деле я компилировал с несколькими файлами. Ниже приведены файлы:

файл main.c ->

#include <stdio.h>
void foo3(void)
{
        printf("INSIDE foo3 function\n");
}

int main()
{
        foo1();
        foo2();
        foo3();
}

файл 1.c ->

#include <stdio.h>
void foo1(void)
{
        printf("INSIDE foo1 function\n");
}

файл 2.c->

#include <stdio.h>
void foo2(void)
{
        printf("INSIDE foo2 function\n");
}

Теперь я скомпилировал с помощью gcc следующим образом ->

gcc 1.c 2.c main.c -o main

Следующий был вывод ->

INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function

Мое сомнение в том, как мог main() вызов foo1() а также foo2() когда они не объявлены в main.c, Но теперь, если я изменю main.c следующим образом (написание определения foo3() после main()) как это:

Отредактировано main.c ->

#include <stdio.h>
int main()
{
        foo1();
        foo2();
        foo3();
}

void foo3(void)
{
        printf("INSIDE foo3 function\n");
}

и затем, если я скомпилирую, я получаю эту ошибку:

main.c:9:6: warning: conflicting types for ‘foo3’ [enabled by default]
 void foo3(void)
      ^
main.c:6:2: note: previous implicit declaration of ‘foo3’ was here
  foo3();
  ^

почему эта ошибка не была показана ранее в случае foo1() а также foo2(), Заранее спасибо.

1 ответ

Решение

Мое сомнение в том, как мог main() вызов foo1() а также foo2() когда они не объявлены в main.c

Поскольку компилятор GCC по умолчанию использует старый язык ANSI C (он же C89), где разрешены необъявленные функции и по умолчанию задано int результат.

Попробуйте вызвать компилятор, например,

 gcc -std=c99 -Wall -g -c main.c

или (если вы хотите скомпилировать все файлы одновременно)

 gcc -std=c99 -Wall -g 1.c 2.c main.c -o main

Вы можете запросить межпроцедурную оптимизацию времени соединения с gcc -flto вместо gcc используя недавний GCC, например, GCC 4.9 в сентябре 2014 года.

Для этого потребуется совместимый исходный код C99, в котором должны быть объявлены все функции. -Wall просит (почти) все предупреждения. -g опция производит отлаживаемый объектный код (или исполняемый файл для последней команды, компилирующей все файлы одновременно).

В вашей редакции main.c когда foo3 первое появление (внутри main), компилятор догадывается, что это функция, возвращающая int, Когда компилятор видит определение foo3 это справедливо жалуется.

Вы могли бы использовать -Wstrict-prototypes опция предупреждения gcc (но это подразумевается -Wall который я всегда рекомендую использовать).

Во время соединения тип (и сигнатура) функций C не имеет значения. Компоновщик просто использует имя для своей работы (но C++ использует искажение имени). Конечно, вызов функции с неверными аргументами или результатом является неопределенным поведением.

Хорошей обычной практикой является наличие общего заголовочного файла, объявляющего все используемые и общедоступные функции и типы (и константы) и включающего этот заголовочный файл в ваши исходные файлы (это позволяет избежать необходимости копировать и вставлять эти объявления несколько раз). Таким образом, вы должны иметь новый заголовочный файл myheader.h лайк

// file myheader.h
#ifndef MY_HEADER_INCLUDED
#define MY_HEADER_INCLUDED
void foo1(void);
void foo2(void);
void foo3(void);
#endif /*MY_HEADER_INCLUDED*/

и вы бы добавили #include "myheader.h" во всех ваших исходных файлах (после #include <stdio.h> директива есть). Обратите внимание на трюк включения охранника с MY_HEADER_INCLUDED,

На практике заголовочные файлы обычно содержат комментарии, объясняющие API вашей программы.

Узнайте также о GNU make. Это облегчит сборку ваших программ с файлами из нескольких исходных кодов (вы просто компилируете и собираете их, запустив make). Смотрите это и это примеры Makefile, Поймите, что предварительная обработка Си - это первая фаза компиляции Си.

Другие вопросы по тегам