Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C如何管理#包含多个源文件之间的关系并创建正确的makefile_C_Struct_Makefile_Header Files - Fatal编程技术网

C如何管理#包含多个源文件之间的关系并创建正确的makefile

C如何管理#包含多个源文件之间的关系并创建正确的makefile,c,struct,makefile,header-files,C,Struct,Makefile,Header Files,我再次编辑了我的问题,这次是最后一次 注意:程序正在运行(感谢所有帮助)。但对于依赖关系/链接实际上是如何工作的,我仍然有些困惑。具体地说,我希望了解makefile编译和运行的过程。(例如,编译器首先查看main.c,从第1行开始,即main.h,进入main.h,从第1行开始,即指向function1.h,依此类推。) 我这里的主要问题是:编译器/makefile是否确实以反向方式运行,即一旦编译器到达最后一个停止点(不再链接),它就开始递归地收集内容并将其放入对象文件中。如果我们有多个对象

我再次编辑了我的问题,这次是最后一次

注意:程序正在运行(感谢所有帮助)。但对于依赖关系/链接实际上是如何工作的,我仍然有些困惑。具体地说,我希望了解makefile编译和运行的过程。(例如,编译器首先查看main.c,从第1行开始,即main.h,进入main.h,从第1行开始,即指向function1.h,依此类推。)

我这里的主要问题是:编译器/makefile是否确实以反向方式运行,即一旦编译器到达最后一个停止点(不再链接),它就开始递归地收集内容并将其放入对象文件中。如果我们有多个对象文件,并且连接是交叉链接的,会发生什么?每个对象文件应该相互独立吗

下面是我的最终结果。 我知道这是一个很大的部分,但我已经尽我最大的努力把他们在一个有组织的方式,并增加了说明

最终制作文件/依赖项

main.c: *include* main.h and *define* system-wide constants (declared in control.h)
main.h: *include* all std libs, *include* control.h, *include* builder1.h, *include* builder2.h

builder1.c: *include* builder1.h, uses system-wide constants, child functions of builder1, and new structures of builder1, stdlib
build1.h: *include* builder1_funcion.h *include* builder1_share.h *include* primary function prototype

builder1_function.c: *include* builder1_function.h
builder1_function.h: *include* builder1_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler1

builder2.c: *include* builder2.h, uses system-wide constants, child functions of builder2, and new structures of builder2, stdlib
build2.h: *include* builder2_funcion.h *include* builder2_share.h *include* primary function prototype

builder2_function.c: *include* builder2_function.h
builder2_function.h: *include* builder2_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler2
文件布局

主要模块:main.c 补充模块:builder1.c,builder2.c builder1_函数.c builder2_函数.c 头文件:main.h control.h builder1.h builder2.h builder1_function.h builder2_function.h builder1_shared.h builder2_shared.h

1) c使用builder1.c和builder2.c中的每一个调用一个主函数

2) builder1_函数、builder2_函数存储builder1.c和builder2.c中主函数使用的子函数

3) builder1有一组它刚刚使用的新结构,builder2有另一组它刚刚使用的新结构。这些结构在builder1_shared.h和builder2_shared.h中声明

4) 函数原型在builder1.h builder2.h main.h中声明

5) main.c、builder1.c、builder2.c共享一些常量,并且都使用标准库。这些常量在control.h中声明

6) control.h:声明系统范围的常量

标题相关性

main.c: *include* main.h and *define* system-wide constants (declared in control.h)
main.h: *include* all std libs, *include* control.h, *include* builder1.h, *include* builder2.h

builder1.c: *include* builder1.h, uses system-wide constants, child functions of builder1, and new structures of builder1, stdlib
build1.h: *include* builder1_funcion.h *include* builder1_share.h *include* primary function prototype

builder1_function.c: *include* builder1_function.h
builder1_function.h: *include* builder1_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler1

builder2.c: *include* builder2.h, uses system-wide constants, child functions of builder2, and new structures of builder2, stdlib
build2.h: *include* builder2_funcion.h *include* builder2_share.h *include* primary function prototype

builder2_function.c: *include* builder2_function.h
builder2_function.h: *include* builder2_shared.h *include* child function prototype

builder_shared.h: *include* main.h, declare new structure for buidler2
MAKEFILE

main: main.o builder1.o builder1_function.o builder2.o builder2_function.o
gcc -o main main.c builder1.c builder1_function.c builder2.c builder2_function.c -g

builder1.o: builder1.c
gcc -c  builder1.c

builder1_function.o: builder1_function.c
gcc -c builder1_function.c

builder2.o: builder2.c
gcc -c builder2.c

builder2_function.o: builder2_function.c
gcc -c builder2_function.c

标题为多个源文件提供信息。如果源文件不向其他文件提供任何服务,则不需要任何头文件。这意味着可能不需要
main.h
,但需要
functions.h
。标头应包含允许使用者使用源代码中定义的函数(和变量)所需的最少代码。任何其他头都应该直接包含在源代码中(因此头应该是小的、自包含的、幂等的)

请注意,与头相对应的主源文件(
main.c
用于
main.h
,或
functions.c
用于
functions.c
)应将头作为第一个包含的文件。这确保了标题是自包含的;如果不是,它就不会编译。来自另一个源文件的每个服务使用者都应该包括相应的头。每个非静态函数(和全局变量,如果有的话)应该在一个头中声明;该标题应在需要函数(或全局变量)的任何位置使用

鉴于您的问题,似乎
functions.c
应该包括
main.h
(因此需要
main.h

在makefile中,您可能应该使用:

OBJECTS = main.o functions.o

all:  main

main: ${OBJECTS}
    ${CC} -o $@ ${OBJECTS} ${CFLAGS} ${LDFLAGS} ${LDLIBS}

main.o:      main.h functions.h
functions.o: functions.h main.h

另见:


标题为多个源文件提供信息。如果源文件不向其他文件提供任何服务,则不需要任何头文件。这意味着可能不需要
main.h
,但需要
functions.h
。标头应包含允许使用者使用源代码中定义的函数(和变量)所需的最少代码。任何其他头都应该直接包含在源代码中(因此头应该是小的、自包含的、幂等的)

请注意,与头相对应的主源文件(
main.c
用于
main.h
,或
functions.c
用于
functions.c
)应将头作为第一个包含的文件。这确保了标题是自包含的;如果不是,它就不会编译。来自另一个源文件的每个服务使用者都应该包括相应的头。每个非静态函数(和全局变量,如果有的话)应该在一个头中声明;该标题应在需要函数(或全局变量)的任何位置使用

鉴于您的问题,似乎
functions.c
应该包括
main.h
(因此需要
main.h

在makefile中,您可能应该使用:

OBJECTS = main.o functions.o

all:  main

main: ${OBJECTS}
    ${CC} -o $@ ${OBJECTS} ${CFLAGS} ${LDFLAGS} ${LDLIBS}

main.o:      main.h functions.h
functions.o: functions.h main.h

另见:

#include
是一个预处理命令,它只包含文本,没有比这更复杂或更神奇的了

因此:

  • 如果.c文件包含使用结构的代码,则需要包含定义该结构的头文件

  • 如果.c文件实现或调用函数,那么它需要包含分解该函数原型的头文件(通常是与实现该函数的.c文件匹配的头文件)

  • 如果.c文件使用某些系统调用或类型,则需要包含相关的系统头文件

一旦您习惯了“包含”的概念,您将能够了解如何高效、优雅地构建模块和头文件,以便于阅读和维护。

\include
是一个预处理命令,它只包含文本,没有比这更复杂或更神奇的了

因此:

  • 如果.c文件包含使用结构的代码,则需要包含定义该结构的头文件