为什么要在.c文件中避免使用#ifdef?

Nor*_*sey 31 c conditional-compilation

我尊重程序员表示,在C代码,#if并且#ifdef应当不惜一切代价避免,除了可能在头文件.为什么#ifdef在.c文件中使用会被视为糟糕的编程习惯?

Ale*_*ski 55

很难维护.更好地使用接口来抽象平台特定代码,而不是通过散布#ifdef整个实现来滥用条件编译.

例如

void foo() {
#ifdef WIN32
   // do Windows stuff
#else
   // do Posix stuff
#endif
   // do general stuff
}
Run Code Online (Sandbox Code Playgroud)

不好.相反,有文件foo_w32.cfoo_psx.c

foo_w32.c:

void foo() {
    // windows implementation
}
Run Code Online (Sandbox Code Playgroud)

foo_psx.c:

void foo() {
    // posix implementation
}
Run Code Online (Sandbox Code Playgroud)

foo.h中:

void foo();  // common interface
Run Code Online (Sandbox Code Playgroud)

然后有2个makefile 1 : Makefile.win, Makefile.psx每个编译相应的.c文件并链接到正确的对象.

小修改:

如果foo()的实现依赖于出现在所有平台上的一些代码,例如common_stuff()2,只需拨打在您的foo()实现.

例如

COMMON.H:

void common_stuff();  // May be implemented in common.c, or maybe has multiple
                      // implementations in common_{A, B, ...} for platforms
                      // { A, B, ... }. Irrelevant.
Run Code Online (Sandbox Code Playgroud)

foo_ {w32,psx} .c:

void foo()  {  // Win32/Posix implementation
   // Stuff
   ...
   if (bar) {
     common_stuff();
   }
}
Run Code Online (Sandbox Code Playgroud)

虽然您可能正在重复函数调用common_stuff(),但您无法参数化foo()每个平台的定义,除非它遵循非常特定的模式.通常,平台差异需要完全不同的实现,并且不遵循这样的模式.


  1. 这里使用Makefile作为说明.您的构建系统可能根本不使用make,例如,如果您使用Visual Studio,CMake,Scons等.
  2. 即使common_stuff()实际上有多个实现,每个平台也不同.

  • 那么,取决于构建系统.您可能没有任何makefile,例如,如果您使用Visual Studio,CMAKE,Scons或任何其他工具.我的例子是说明性的. (4认同)
  • 不需要多个makefile.这就是配置脚本的用途. (3认同)

pau*_*aul 6

(有点问题)

我曾经看过一个提示,建议使用#if(n)def/#endif块来调试/隔离代码而不是注释.

有人建议帮助避免被评论的部分已经有文件评论的情况,并且必须实施如下的解决方案:

/* <-- begin debug cmnt   if (condition) /* comment */
/* <-- restart debug cmnt {
                              ....
                          }
*/ <-- end debug cmnt
Run Code Online (Sandbox Code Playgroud)

相反,这将是:

#ifdef IS_DEBUGGED_SECTION_X

                if (condition) /* comment */
                {
                    ....
                }
#endif
Run Code Online (Sandbox Code Playgroud)

对我来说,这似乎是一个巧妙的想法.希望我能记住源,所以我可以链接它:(

  • 我只是使用`#if 0 ... #else ... #endif`暂时更改代码以进行调试.然后将0更改为1以返回原始代码. (3认同)