对于许多问题,这个问题的答案取决于。与其说这是更好的我已经相当给出的例子和目标,其中一个比其他更好。
预处理程序和常量都有其自己的适当用法位置。
如果是预处理器,则在编译之前删除代码。因此,它最适合预期不编译代码的情况。这可能会影响模块的结构,依赖性,并且可能允许针对性能方面选择最佳的代码段。在以下情况下,必须仅使用预处理程序来划分代码。
多平台代码:
例如,当代码在不同平台上编译时,当代码依赖于特定的OS版本号(甚至是编译器版本-尽管这种情况很少见)时。例如,当您在处理低端代码和大端代码时,它们必须与预处理程序而不是常量分开。或者,如果您要同时为Windows和Linux编译代码,则某些系统调用会大不相同。
实验性补丁程序:
这样做的另一种情况是证明其合理性是某些实验性代码存在风险,或者某些主要模块需要省略,这将导致明显的链接或性能差异。之所以要通过预处理器禁用代码而不是将其隐藏在if()下,是因为我们可能不确定此特定更改集引入的错误,并且我们正在实验的基础上运行。如果失败,除了重写,我们在生产中除了禁用该代码外别无选择。一段时间以来,最好使用#if 0
注释掉整个代码。
处理依赖关系:
您可能希望生成的另一个原因例如,如果您不想支持JPEG图像,则可以帮助您摆脱对该模块/存根的编译,最终库将不会(静态或动态)链接到该模块/存根。模块。有时,程序包会运行./configure
以识别这种依赖关系的可用性,并且如果不存在库(或用户不想启用),则会自动禁用此类功能,而无需与该库链接。如果自动生成这些指令,则总是有益的。
许可:
预处理程序指令的一个非常有趣的示例是ffmpeg。它具有编解码器,使用该编解码器可能会侵犯专利。如果您下载源代码并进行编译安装,它将询问您是否要保留这些东西。如果条件仍然可以使您出庭,将密码隐藏在某些情况下!
代码复制粘贴:
Aka宏。这并不是过度使用宏的建议-只是宏具有更强大的方式来应用等效于复制-过去的方式。但是要小心使用;如果知道自己在做什么,就使用它。常量当然不能这样做。但是inline
如果这很容易的话,也可以使用函数。
那么什么时候使用常量呢?
几乎其他任何地方。
整洁的代码流:
通常,使用常量时,它与常规变量几乎没有区别,因此,它是可读性更好的代码。如果您编写的例程为75行,则#ifdef每10行之后会有3或4行非常无法读取。可能给定一个主要常量,该常量由#ifdef控制,并在任何地方以自然流动的方式使用它。
缩进良好的代码:所有预处理器指令,永远不能与缩进良好的代码一起使用。即使您的编译器确实允许缩进#def,ANSI C之前的预处理器也不允许在行首与“#”字符之间留空格。前导“#”必须始终放在第一列中。
配置:
常量/或变量有意义的另一个原因是,它们可以很容易地从链接到全局变量或将来扩展为从配置文件派生而来。
最后一件事:
永远不要使用预处理程序指令#ifdef
来#endif
跨越范围或{ ... }
。即在的不同边的开始#ifdef
或结束。这是非常糟糕的。这可能会造成混淆,有时可能会很危险。#endif
{ ... }
当然,这并不是一个详尽的清单,但会显示出明显的区别,即哪种方法更易于使用。这是不是真的了解这是更好的,它常是更多的哪一个更自然的在给定环境中使用。