'中可能存在的缺陷;包括*.c文件';风格C编程
我通过以下方式遇到了一些代码'中可能存在的缺陷;包括*.c文件';风格C编程,c,C,我通过以下方式遇到了一些代码 //file.c #include <stdlib.h> void print(void){ printf("Hello world\n"); } //file.c #包括 作废打印(作废){ printf(“Hello world\n”); } 及 //文件main.c #包括 #包括“file.c” int main(int argc,char*argv[]){ 打印(); 返回退出成功; } 这种编程风格有什么缺陷吗?虽然我觉
//file.c
#include <stdlib.h>
void print(void){
printf("Hello world\n");
}
//file.c
#包括
作废打印(作废){
printf(“Hello world\n”);
}
及
//文件main.c
#包括
#包括“file.c”
int main(int argc,char*argv[]){
打印();
返回退出成功;
}
这种编程风格有什么缺陷吗?虽然我觉得有缺陷,但我还是无法理解,因为我在某处读到,将实现分离为*.h和*.c文件有助于编译器检查一致性。我不明白什么是一致性。我非常感谢你的建议
--谢谢在.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;
}
//file.h
作废打印(作废);
//文件.c
无效的
打印(作废)
{
printf(“Hello world\n”);
}
//文件main.c
#包括
#包括“file.h”
int main(int argc,char*argv[]){
打印();
返回退出成功;
}
如果将file.c包含在多个源代码文件中,这些源代码文件组合成库/可执行文件,则会出现问题,因为您将有重复的方法实现。我觉得上述方法在共享/重用代码方面效果不佳,不推荐使用。没有任何东西可以阻止您包含.c文件。但是,将声明(在.h文件中)和实现(以及.c文件)分开,然后只包含.h文件有几个优点:
- 编译时。声明的更改通常小于实现的更改。如果只包含.h文件,并在实现中进行了更改(在.c文件中),则只需重新编译一个.c文件,而不必重新编译包含修改后的文件的所有文件
- 界面的可读性和管理。您的所有声明都可以在(通常)小的.h文件中一目了然地进行检查,而.c文件中填充了一行又一行的代码。此外,它还可以帮助您确定哪个文件,查看哪些函数和变量。例如,避免在不需要全局变量的地方包含它
- 编译器应该编译
.c
文件是一种常见的期望.h
文件不会直接提供给编译器。它们通常只包含在.c
文件中
因此,您的代码需要通过以下方式编译:
gcc main.c file.c
而不仅仅是
gcc main.c
。该命令在链接阶段会失败,因为它会看到重复的符号。从C语言的角度来看,在程序中包含.C文件没有什么错。C语言不关心文件的扩展,C++实际上经常忽略某些头文件的扩展,避免冲突。
但是从程序员的角度来看,是的,这很奇怪。大多数程序员都会假设不包含.c文件,这可能会由于错误的假设而导致问题。最好避免这种做法。如果你发现你必须使用它,那就是设计拙劣的标志。是的,这是允许的 使用这是一个高级主题
- 它减慢了开发编译时间(只编译必要的东西更便宜)
- 它加快了部署编译时间(所有文件都已过期)
- 它允许编译器跨模块边界内联函数
- 它允许一种技巧来控制从库中导出的符号,同时保持其模块化
- 这可能会混淆调试器
我建议使用不同的文件扩展名以避免混淆(例如.*.inc、*.dat等)。我只知道包含C文件的两个原因(这是有意义的):
- 内联函数非常重要,但这实际上是一个风格问题
- 通过在多个其他文件中包含同一文件来共享私有(静态)函数的实现。实际上,这是以完全独立于平台的方式实现这一点的唯一方法(但特定于工具链的技巧,如gcc的隐藏属性等,如果可用的话,效果会更好)
- 同一代码要编译多次
- 如果不谨慎使用,它会很快导致公共符号的多个已定义符号,这种方式很难调试(包括包含其他文件的文件…)
MyTemplateFunction_ ## MYTYPE(MYTYPE x)
{
// function code that works with all used TYPEs
}
主要条款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;
}
宏的邪恶可能会加剧: 文件1.c
#define bottom arse
文件2.c
int f()
{
int arse = 4;
bottom = 3;
printf("%d", arse);
}
main.c
#include "file1.c"
#include "file2.c"
void main()
{
f();
}
这确实是一个复杂的例子。但通常您不会注意到它,因为宏的作用域就是它所在的文件
我确实遇到了这个bug,我正在将一些lib代码导入到一个新项目中,不想费心编写Makefile,所以我只生成了一个all.cpp,其中包含了库中的所有源代码。而且由于宏观污染,它并没有像预期的那样工作。我花了一段时间才弄明白。对于这种长度的程序来说没问题。在代码前面加上4个空格(或选择编辑器工具栏中的“代码”按钮)会使代码显示为代码。代码片段不需要反勾号。file1.c是一个示例,说明了在包含的文件中存在可执行代码,而不是正在使用的实际程序。是的,我注意到现在再次阅读他的问题。我读了#include“file.h”,没有注意到真正的问题。
#include "file1.c"
#include "file2.c"
void main()
{
f();
}