Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.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 - Fatal编程技术网

'中可能存在的缺陷;包括*.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文件,这可能会由于错误的假设而导致问题。最好避免这种做法。如果你发现你必须使用它,那就是设计拙劣的标志。

      是的,这是允许的

      使用这是一个高级主题

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

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


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

      我只知道包含C文件的两个原因(这是有意义的):

      • 内联函数非常重要,但这实际上是一个风格问题
      • 通过在多个其他文件中包含同一文件来共享私有(静态)函数的实现。实际上,这是以完全独立于平台的方式实现这一点的唯一方法(但特定于工具链的技巧,如gcc的隐藏属性等,如果可用的话,效果会更好)
      缺陷:

      • 同一代码要编译多次
      • 如果不谨慎使用,它会很快导致公共符号的多个已定义符号,这种方式很难调试(包括包含其他文件的文件…)

      这是一种糟糕的风格,但另一个原因是,它可以作为一种技巧的一部分,使用来完成C语言中的穷人模板

      请注意,不建议这样做,因为这样会产生难以调试和维护的代码,但您可以执行以下操作:

      mytemplate.c:

      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();
      }