Вызов функций из другого файла 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
, Поймите, что предварительная обработка Си - это первая фаза компиляции Си.