Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.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文件中包含一个.c文件可以吗?_C_Struct_Include - Fatal编程技术网

在另一个.c文件中包含一个.c文件可以吗?

在另一个.c文件中包含一个.c文件可以吗?,c,struct,include,C,Struct,Include,例如: file1.c有: 文件2.c有: 等等 可以这样做吗?不,您应该始终避免包含c文件 头文件应仅包含定义/原型 c文件包含函数,不应包括在内。从技术上讲,它只是文件名,扩展名.c对文件内容没有影响,如果需要,可以调用.z。所以要回答你的问题:是的,你能做到。但它确实违反了惯例,它应该在头文件中 这样可以吗?请让我知道。谢谢 这在技术上是可行的,但我不建议这样做。相反,我建议将声明放在头文件中,然后在项目/makefile/等中同时包含这两个.c文件 这将更像是一种标准的工作方式,从而使您

例如:

file1.c有:

文件2.c有:

等等


可以这样做吗?

不,您应该始终避免包含c文件

头文件应仅包含定义/原型


c文件包含函数,不应包括在内。

从技术上讲,它只是文件名,扩展名.c对文件内容没有影响,如果需要,可以调用.z。所以要回答你的问题:是的,你能做到。但它确实违反了惯例,它应该在头文件中

这样可以吗?请让我知道。谢谢

这在技术上是可行的,但我不建议这样做。相反,我建议将声明放在头文件中,然后在项目/makefile/等中同时包含这两个.c文件


这将更像是一种标准的工作方式,从而使您的项目更易于维护。

您可以在这里找到问题的好答案:


我自己会将其保存为头文件file1.h,并将其包括在内。

避免这样做。将对项目的其他部分有用/必要的任何类型定义和函数签名从file1.c中拉到公共头文件中,而不是包含在项目的其他部分中


通常情况下,在file2.c中包含file1.c是可行的,因为文件包含只是用另一个文件的内容替换包含,但随着项目复杂性的增加,这将开始中断,并且您开始遇到多定义符号的问题。

是的,只要您有很好的动机,就可以了。例如,它可以帮助您避免源代码重复,即使您仍然会在二进制级别获得重复,或者它可以允许您处理机器生成的代码片段,例如,由单独的编译器生成的解析器。在某些平台上,您甚至可以获得一些性能或占用空间方面的改进,因为编译器可以选择更优化的指令,例如,在file1.c包含代码的情况下,如果file1.c是一个单独的翻译单元,则不可能选择相对的本地调用

如果你的动机不够好,应该避免,因为它可能会在一些方面造成麻烦。我想到的几个问题是:

您的构建系统可能不够智能,无法检测到对file1.c的依赖 您的编辑器或开发环境可能不够智能,无法从file1.c中找到符号 如果不是您在文件1.c中定义的所有符号都具有内部链接,则可能会导致链接错误。
这里基本上没有技术方面的考虑。也就是说,这个决定基本上与软件或硬件的运行方式无关

本决定中的考虑因素是人为因素。当我们就如何组织源代码做出决策并创建约定时,我们这样做是为了实现以下目标:使代码更易于编写。使代码更易于维护。减少错误

这些都是人为的考虑。人类的行为方式不同于完美的机器:他们会犯错。他们会忘记事情。它们可以更好地处理分为可管理大小的问题

通常,头文件用于声明多个源文件中使用的内容,例如由许多不同的人在许多不同程序中使用的库例程,并将声明与定义分开,因此,您可以编译使用例程的源文件,而不必在源文件中包含这些例程的定义。从技术上讲,您可以将声明复制到每个源文件中,并且可以从编译器获得相同的结果。但这违反了几个目标:它使代码更难编写,因为每当例程定义发生更改时,都必须更改声明的所有副本。它增加了错误:有时,人们会忘记或错过需要更改的副本之一

因此,您可以将struct对象的定义放入.c文件中。您还可以将其放入头文件中。这会帮助你实现你的目标吗

请注意,struct对象被声明为静态的。如果在多个源文件中编译,则生成的每个目标文件都将有一个单独的副本。当您将对象文件链接到单个可执行文件时,它将具有相同数据的多个副本,除非您使用的开发人员工具非常非常好。这是一种浪费,所以这不是一个好主意。但是,如果您只在一个源文件中编译它,那么只有人为的考虑才是重要的:您是否有可能犯错误并同时编译file1.c和file2.c?当其他人处理这段代码时,他们会理解mystruct是如何定义的以及为什么定义的吗?等等

我曾经在一些项目中工作过,在这些项目中,在单独的源文件中定义对象是合适的。例如,有时需要准备一个com表 输入数据并将其包含在程序源中。在这种情况下,将该表保存在单独的源文件中是合理的

通常,这种情况下使用的解决方案是使用只包含表定义而不包含其他内容的源文件。在该源文件中,将使用“extern”关键字将表声明为外部表。在头文件中,该表将被声明但未定义。使用该表的每个源文件都将包含用于声明该表的头文件。定义表的源文件还包括头文件。当您这样做时,如果头文件和源文件之间存在任何不匹配,编译器将发出抱怨。这样可以避免头文件中的错误

定义表的源文件将被编译成一个对象模块。包含程序其他内容的源文件将被编译成单独的对象模块。然后使用链接器将所有目标模块合并到一个程序中

在您的情况下,是否有任何理由将对象声明为静态的?如果有,那么在另一个源文件中包含其定义的解决方案可能是合适的。然而,很少有这样的理由。如果您认为将定义放在单独的文件中有助于组织源代码,那么更合适的解决方案可能是如上所述将对象声明为外部对象,并单独编译源代码

使用GCC时,您可以将源代码编译为如下所示的对象模块:

gcc-c-o name0.o name0.c gcc-c-o name1.o name1.c

“-c”开关表示“只是编译到对象并停止,而不是执行下一步链接以生成可执行文件。”“-o”开关指定输出文件的名称

然后,您可以将对象模块链接到如下可执行文件:

gcc-o程序名0.o名称1.o


我建议,虽然有时包含一个包含实际代码或数据定义的文件可能会很有用,而不仅仅是声明,但我不喜欢使用.c扩展名命名文件,除非它们设计为直接编译。我通常命名那些设计为包含但包含更多的文件例如,在我使用的一个嵌入式处理器上,访问静态结构元素的代码大约是访问给定结构指针的元素的代码的四分之一大小,运行速度大约是访问给定结构指针的元素的代码的四倍诚然,代码需要合理快速地运行,并且代码可能必须在两个结构上运行,为这两个结构生成代码的单独副本比生成一个可以使用的代码副本更有效。如果不考虑速度,则可能有在其中一个结构上运行的代码他创建了一个结构,以及一个交换结构内容的例程。要对第二个结构进行操作,请交换结构,对第一个结构进行操作,然后将它们交换回来

实现此习惯用法的首选方法是执行以下操作:

#define THINGIE 0 #define THINGIE_STRUCT thingie0 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE #define THINGIE 1 #define THINGIE_STRUCT thingie1 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE
有点难看,但有时在间接结构访问非常糟糕的机器上是值得的。

您不需要也给您的变量命名吗?!一般来说,不,这不好。为什么要这样做?它工作……但非常难看。不要这样做!为什么文件1是一个.c文件?谢谢,但这两个.c文件如何?我的意思是how 2.c文件?@RRR使用makefile。请参阅:谢谢,但是file1.c只有struct定义。可以吗?@RRR您应该将它放在header.h文件中。现在,my.c文件只包含struct定义。它仍然不可以吗?它不仅包含定义,还包含声明。您可能必须在一个文件中使用extern关键字,然后使用e另一个中的实际声明。类型本身结构可以保留在头文件中。您链接的问题实际上与此问题完全重复。
#include <stdio.h>
#include "file1.c"
#define THINGIE 0 #define THINGIE_STRUCT thingie0 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE #define THINGIE 1 #define THINGIE_STRUCT thingie1 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE