使用放在另一个目录中的另一个C文件的函数?

假设我有一个父目录A,有两个子目录B和C.

子目录C有一个helper.c和helper.h,如下所示:

//helper.c

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


//helper.h

void print();

现在,在子目录B中,我有一个main.c,它只调用print函数:

//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

现在我从main .c中删除了#include“../ C / helper.h”并再次尝试了Command 2.它仍然有效.

所以我有以下问题:

i)是否包含helper.h文件有什么区别
      helper.c?

ii)为什么命令1失败?

iii)有没有办法编译我的C程序而无需指定
         helper.c每次?

最佳答案 首先,您需要了解#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代码文件(或任何文件)时,这些定义将合并到您的代码中,链接器将具有它们,这就是它工作的原因.

至于你的第三个问题
将c文件直接包含在其他c文件中是不好的做法,常见的方法是保留单独的c文件,其中包含暴露其提供的功能的标头,包括头文件和链接到已编译的c文件,例如在您的情况下:

gcc main.c helper.c -o out

将允许你在main.c中包含helper.c并且仍然有效,因为你指示编译器编译两个文件而不仅仅是main.c所以当链接发生时,将找到编译中的定义,你将不会得到未定义的行为错误

简而言之,这就是.我抽象了许多正在传递的概念. this是一篇很好的文章,详细描述了编译过程,this是对整个过程的一个很好的概述.

点赞