2014-09-02 6 views
0

Фактически я компилировался с несколькими файлами. Ниже перечислены файлы:вызов функций из другого 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

My doubt is how could main() call foo1() and foo2() when they are not declared in 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 

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

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

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

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

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

Хорошая обычная практика иметь общий файл заголовка, объявляя все используемые и общественные функции и типы (и константы) и include, что заголовок файла в ваших исходных файлах (это позволяет избежать придется копировать и вставлять эти объявления несколько раз). Таким образом, вы whould есть новый файл заголовка 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> директивы там). Обратите внимание на трюк include guard с MY_HEADER_INCLUDED.

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

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

+0

благодарю вас за ценную информацию. еще одно сомнение. почему он не показывает предупреждение о конфликтующих типах для foo2() и foo1(), когда они также появляются впервые в main(), например foo3() без какого-либо предыдущего объявления в main.c. – Akhil

+0

Для этого вам нужна оптимизация времени ссылки. Но для вас важно привыкнуть писать и использовать ваши файлы заголовков и объявлять все публичные вещи там. –

+0

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