C语言中#ifdef和#if的用途是什么

新手上路,请多包涵

在我的项目代码中,我发现有人在代码中使用了 #ifdef#if 。我想知道使用它们的目的是什么?据我所知,它对预处理器说不会在该代码中执行任何操作。下面的代码给出了两个使用它们的例子。我试图找到 TEST_PURPOSE (真/假)的定义,但找不到。从下面的代码中,如何在 #ifdef TEST_PURPOSE 里面做一些事情?我正在使用视觉工作室 2012

 #ifdef TEST_PURPOSE
    int i=1;
    printf("Something %d,"i);
#endif

#if 0
  int i=1;
  printf("Something %d,"i);
#endif

原文由 Jame 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

#ifdef 的含义是,只有定义了前面提到的预处理器宏,块内的代码才会被包含在编译中。类似 #if 意味着只有当表达式的计算结果为真时才会包含块(当用0替换出现在表达式中的未定义宏时)。

这里重要的一点是预处理器在编译之前处理源代码,如果不包含该块,则实际编译器根本不会对其进行解析。这是结构的一个重要特征。

现在由于某种原因 C/C++ 使用它。这些语言以线性顺序处理文件,因此出现在源代码下方的内容尚不为人所知,而更重要的内容则出现在其他源文件中。这意味着没有(好的)自动方式可以在另一个源文件中引用一个源文件中的符号,特别是如果您希望类型正确。这意味着您必须拥有原型和 extern 定义才能引用这些。此外,如果两个源文件应该共享数据类型( struct s 和 enum s),则必须这样做。

为了使其更实用,可以将它们放在每个源文件可以 #include 的头文件中(这基本上意味着将头文件插入到实际编译器看到的内容中)。这反过来很容易导致一个头文件包含另一个头文件的情况,您可能会遇到同一个文件被包含两次的情况。由于重复 struct 定义是无效的,因此需要确保相同的头文件没有定义两次 - 这就是 #ifndef 在包含保护中派上用场的地方:

 #ifndef HEADER_INCLUDED_
#define HEADER_INCLUDED_

// actual payload of the header file

#endif

此外,在文件的解析和编译需要很长时间的情况下,这可能会导致加速,因为可以快速跳过标头的有效负载(预处理阶段处理源代码的速度比实际编译阶段快得多)。

“需要”宏的另一个原因是早期的 C 编译器可能只是直接将代码翻译成汇编程序。您可以通过使用宏来避免函数调用,这会导致它的扩展将直接插入到现场并在此处生成代码,而不必进行函数调用。同样的事情也适用于常量,否则这些常量是必须在其他地方获取的变量,而不是直接放入生成的代码中。

第三个原因是条件编译的可能性。大多数编译器预定义了一组宏,旨在提供有关正在编译的系统的信息。例如,我们有宏 _WIN32 仅在您为 Windows 编译时才定义。这将有可能拥有一个仅包含在 windows 中的代码片段,而另一个将包含在另一个平台上的代码片段。大多数编译器还可以从命令行设置自定义宏,这意味着可以从命令行(在 Visual Studio 中,您也可以在项目设置中更改它们)更改将被编译的部分。最引人注目的此类宏是 NDEBUG 宏,如果定义该宏将禁用所有 assert s - 在编译版本时添加 /DNDEBUG 是正常的。

原文由 skyking 发布,翻译遵循 CC BY-SA 3.0 许可协议

#ifdef#if 是预处理器指令,它们甚至在代码编译之前就被评估。

预处理器指令有很多用途,在您的示例中: #ifdef#if 用于在编译中包含或排除代码的某些部分。

强调:在构建过程中完全不存在excluded as in!

您可以在不活动的预处理器块中出现乱码。

注意#if defined(A)#ifdef A 相同,所以我只会参考 #if

使用 1 - 禁用通过链包含处理相同的头文件。

最常见的用途是“头部防护”:

通过 #include 链接您可能会重新进入同一个 H 文件并产生无法预料的现象,因此,使用以下构造很常见

#if !defined(MyHeader_H)
#define MyHeader_H

...

#endif

开始时, MyHeader_H 不会被定义构造,将被处理,包括 MyHeader_H

在后续调用中, #ifndef MyHeader_H,H 文件不会包含在模块中。

使用 2 - 定义配置

有些项目有多种配置,比如说使用不同的硬件类型或一些不同的行为。

你可以这样写:

 #if defined(FLASH_TYPE_A)
code to use flash type A
#elif defined (FLASH_TYPE_B)
code to use flash type B
#else
ASSERT("NO FLASH TYPE DEFINED!");
#endif

在此代码中,您可以在编译期间使用 /dFLASH_TYPE_A/dFLASH_TYPE_B 来定义将包含哪些代码…

注意:与使用标准 if() 语句有区别,

在本例中,二进制文件中只包含一个代码。


还有更多用途,但我认为这些是最常见的!

原文由 Tomer W 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题