2009-06-20 57 views
3

我碰到一些代码以下面的方式来可能出现的瑕疵“包括* .c文件”式C编程

//file.c 
#include <stdlib.h> 

void print(void){ 

    printf("Hello world\n"); 
} 

//file main.c 
#include <stdio.h> 
#include "file.c" 

int main(int argc, char *argv[]){ 

    print(); 

    return EXIT_SUCCESS; 
} 

是否有这样的编程风格的任何缺陷?虽然我感觉如此,但我无法弄清楚这个缺陷,因为在某处我读到将实现分隔为* .h和* .c文件有助于编译器检查一致性。我不明白一致性意味着什么。
我会非常感谢一些建议。

--thanks

+1

将代码前缀为4个空格(或在编辑器工具栏中选择代码按钮)使其显示为代码。你不需要代码片断反引号。 – 2009-06-20 14:29:15

回答

2

如果将数据与代码分离起来更方便,将数据包含在另一个文件中并不罕见。例如,可以包含字符数组中的XPM或原始BMP数据,以这种方式在程序中嵌入图像。如果数据是从另一个构建步骤生成的,那么包含该文件是有意义的。

我建议使用不同的文件扩展名以避免混淆(例如* .inc,* .dat等)。

0

在你应该把函数原型的.h文件。例如,在你的代码,你应该有:

//file.h 
void print(void); 

//file.c 
void 
print(void) 
{ 
    printf("Hello world\n"); 
} 
//file main.c 
#include <stdio.h> 
#include "file.h" 

int main(int argc, char *argv[]){ 

    print(); 

    return EXIT_SUCCESS; 
} 
+1

file1.c是一个例子,显示了包含文件中有可执行代码而不是正在使用的实际程序。 – 2009-06-20 14:38:41

6

你会遇到问题如果您在多个源代码文件file.c这相结合,使库/可执行文件,因为你有重复的方法实现。上述情况让我感到共享/重复使用代码的可能性很低,不推荐使用。

9

没有什么能阻止你包含.c文件。然而,分离声明(在.h文件)和实现(.c文件),然后只包括.h文件有以下几个优点:

  • 编译时间。你的声明通常变化小于你的实现。如果只包含.h文件,并在实现中进行更改(在.c文件中),则只需重新编译一个.c文件,而不是包含修改文件的所有文件。

  • 接口的可读性和管理。所有的声明都可以在(通常)很小的.h文件中查看,而.c文件则是用行和代码行填充的。此外,它可以帮助您确定哪个文件查看哪些函数和变量。例如,为了避免在不需要的地方包含全局变量。

9

这是一个普遍的期望,编译器应该编译.c文件。 .h文件不会直接提供给编译器。它们通常只包含在.c文件中。

因此,你的代码预计类似编译:

gcc main.c file.c 

,而不是只gcc main.c。该命令会在链接阶段失败,因为它会看到重复的符号。

0

从C语言的角度来看,在程序中包含.c文件并没有什么错误。 C语言不关心文件的扩展,实际上C++通常会忽略某些头文件的扩展以避免冲突。

但是从程序员的角度来看,这很奇怪。大多数程序员的操作假定不会包含.c文件,这可能会通过错误的假设导致问题。最好避免这种做法。如果你发现你必须使用它,这是一个设计不佳的标志。

2

是的,这是允许的。

使用这是一个高级主题。

  • 它减慢了开发编译时间(只需要编译便宜)。
  • 它加快了部署编译时间(所有文件都过期)。
  • 它允许编译器跨模块边界内联函数。
  • 它允许从库中控制导出的符号,同时保持它的模块化。
  • 它可能会混淆调试器。
0

只有两个原因,我知道了,包括C文件(和意义):

  • 内联函数,它们不平凡,但这是真正的风格
  • 份额实现方式的问题私人(静态)功能通过在其他几个文件中包含相同的文件。这实际上是做一个纯粹的独立于平台的方式,只有这样(但具体的工具链一样的技巧隐藏属性的GCC,等等......是,如果他们是可用的要好得多)

的缺陷:

  • 编译几次相同的代码
  • 如果没有节制地使用,它迅速导致多个定义的符号的公共符号,从某种意义上说这是难以调试(包括文件,其中包括其他文件...)
0

这是不好的风格,但另一个原因是它可以使用## token concatenation operator做一种穷人的模板在C中的一部分技巧。

请注意,这相当邪恶,isn' T建议的,并将产生的代码很难调试和维护,但你可以类似如下:

mytemplate.c:

MyTemplateFunction_ ## MYTYPE(MYTYPE x) 
{ 
    // function code that works with all used TYPEs 
} 

的main.c:

#define MYTYPE float 
#include "mytemplate.c" 
#undef MYTYPE 

#define MYTYPE int 
#include "mytemplate.c" 
#undef MYTYPE 

int main(int, char*) 
{ 
    float f; 
    int i; 
    MyTemplateFunction_float(f); 
    MyTemplateFunction_int(i); 
    return 0; 
} 
0

宏的罪恶可以加剧:

file1.c中

#define bottom arse 

文件2。Ç

int f() 
{ 
    int arse = 4; 
    bottom = 3; 
    printf("%d", arse); 
} 

的main.c

#include "file1.c" 
#include "file2.c" 

void main() 
{ 
    f(); 
} 

事实上旋绕例子。但通常你不会注意到它,因为宏的范围就是它所在的文件。

我确实得到了这个错误,我正在将一些lib代码导入到一个新项目中,并且无法编写Makefile ,所以我只生成了一个包含库中所有源的all.cpp。由于宏观污染,它没有按预期工作。花了我一段时间才弄明白。

0

这段长度的程序很好。