2016-07-04 2 views
3

Скажем, у меня есть родительский каталог с двумя подкаталогами B и C.Использование функции из другого файла C, помещенного в другой каталог?

подкаталог C имеет helper.c и helper.h, как показано:

//helper.c 

void print(){ 
    printf("Hello, World!\n"); 
} 


//helper.h 

void print(); 

Теперь, в подкаталог B, у меня есть main.c, который просто вызывает функцию печати:

//main.c 

#include<stdio.h> 
#include"../C/helper.h" 

void main(){ 
    print(); 

} 

Я попытался следующие команды для компиляции main.c:

Command 1: gcc main.c //Gives undefined reference to 'print' error 
Command 2: gcc main.c ../C/helper.c //Compiles successfully 

Теперь я удалил #include "../ C/helper.h" из основного .c и снова попробовал команду 2. Он по-прежнему работает.

Так что у меня следующие вопросы:

я) Какая разница, сделать ли включен файл helper.h или helper.c?

ii) Почему команда 1 не работает?

III) Есть ли способ, чтобы составить свою программу C без указания helper.c каждый раз?

ответ

0

Попробую ответить:

я) Какое это имеет значение, является ли файл helper.h включен или helper.c?

Когда вы включаете файл, вы не хотите подвергать свою реализацию, поэтому его лучше включить h файлы, которые содержат только «подписи», - апи вашей реализации.

ii) Почему команда 1 не работает?

При компиляции вы должны добавить все свои ресурсы в исполняемый файл, иначе он не будет компилироваться.

iii) Есть ли способ скомпилировать мою программу на C без указания helper.c everytime?

  • Вы можете использовать Makefile скомпилировать программу. Может быть, this учебник может вам помочь.
0

я) Какое это имеет значение, является ли файл helper.h включен или helper.c?

В том числе helper.c означает, что helper.c каждый раз компилируется, как если бы он был частью основного.с

Включая helper.h позволяет компилятору знать, какие типы аргументов функция печати() принимает и возвращает так что компилятор может дать ошибку или предупреждение, если вы звоните печать() неправильно

II) Почему команда 1 не удается?

Компилятору не сообщается, где найти фактический код для функции печати. Как объяснено, в том числе .h-файл помогает компилятору с проверкой типов.

iii) Есть ли способ скомпилировать мою программу на C без указания helper.c everytime?

Вы можете скомпилировать его один раз в объектный файл и, при необходимости, добавить объект obj в статическую или динамически загруженную библиотеку. Вам все равно нужно помочь компилятору найти obj или библиотеку. Например,

gcc -c helper.c 
gcc main.c helper.o 

Правильный способ избежать компиляции модулей, которые не нуждаются в компиляции, - использовать Makefile. Файл Makefile сравнивается, когда последний модуль компилировался по сравнению с тем, когда он был последним изменен, и таким образом он знает, что нужно компилировать, а что нет.

1

Прежде всего, необходимо понять, что #include просто добавляет любой текст в параметре на позицию в файле оператор находится в #include, например:

//file1.h 
void foo(); 

//main.c 
#include "file1.txt" 
int main(int argc, char **argv) 
{ 
    foo(); 
    return 0; 
} 

заставит предварительно компиляции для создания этой единый файл для компиляции:

//main.c.tmp 
void foo(); 

int main(int argc, char **argv) 
{ 
    foo(); 
    return 0; 
} 

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

Когда вы включаете c-файл кода (или любой файл), содержащий определения, эти определения будут объединены с вашим кодом, а линкер будет иметь их, поэтому он работает.

и, как для третьего вопроса Это плохая практика включают гр-файлы непосредственно в других гр файлов, общий подход, чтобы сохранить отдельные файлы Си с заголовками обнажая функциональность они предоставляют, включает в себя файлы заголовки и ссылка на скомпилированные файлы Си, например, в вашем случае:

gcc main.c helper.c -o out

позволит вам включить helper.c в основном.с и до сих пор работает, потому что вы поручили для компиляции оба файла, а не только main.c поэтому, когда связь происходит будут найдены определения из компиляции и вы не получите undefined behavior ошибку

Это, в двух словах. Я отвлекся от того, что происходит, чтобы передать общую идею. this - хорошая статья, описывающая процесс компиляции в деталях, и this - хороший обзор всего процесса.

1

Что происходит, когда вы выполняете:

Command 1: gcc main.c //Gives undefined reference to 'print' error 

Когда выполнить GCC main.c компилятор компилирует main.c и создает объективный файл. Этот файл будет содержать неразрешенную ссылку на функцию print(). Поскольку в файле main.c отсутствует реализация функции print(). После компиляции gcc пытается сделать полный исполняемый файл. Для этого gcc объединяет все объективные файлы и пытается разрешить все неразрешенные ссылки. Как вы помните, существует неразрешенная ссылка для функции print(), gcc не может найти реализацию и поднять ошибку.

При выполнении

Command 2: gcc main.c ../C/helper.c //Compiles successfully 

GCC компилирует оба файла. Второй файл ../C/helper.c содержит реализацию функции print(), поэтому компоновщик может найти его и разрешить ссылку на него в функции main().

i) Какая разница в том, включен ли helper.h-файл или helper.c?

В вашем случае helper.h содержит декларацию функции print(). Это дает компилятору информацию о том, как сделать вызов функции print().

ii) Почему команда 1 не работает?

См. Выше.

iii) Есть ли способ скомпилировать мою программу на C без необходимости указывать helper.c каждый раз?

Используйте утилиту make. Скомпилируйте helper.c в отдельный целевой файл helper.o и используйте его в команде linkage.

helper.o: ../C/helper.c ../C/helper.h 
     gcc -c ../C/helper.c 

main.o: main.c main.h 
     gcc -c main.c 

testprog: main.o helper.o 
     g++ main.o helper.o -o testprog 

Подробнее см. В руководстве по эксплуатации. Команды TAD должны иметь отступы.

 Смежные вопросы

  • Нет связанных вопросов^_^