#ifdef MACRO 相当于注释吗

2024-05-05

假设 MACRO 没有定义,这些是等价的

#ifdef MACRO
    Not valid C or C++ code
#endif

/*
    Not valid C or C++ code
*/

在 GCC 4.7.1 中,它似乎是等效的,但是否有预处理器可以做更多的事情?


这取决于“无效的 C 或 C++ 代码”的含义。

a 内的文字comment不必遵守大多数语言规则。它甚至没有被标记化。这是完全有效的:

/* This comment doesn't contain a valid sequence of preprocessing tokens
   (because of the apostrophe).  */

它必须遵守的唯一规则是控制评论结束位置的规则。人们经常会被行注释中的反斜杠换行符绊倒(事实上,SO 的语法荧光笔曾经犯过这个错误!)

// Line comment with ascii art ending with a \
   Oops! This line is commented out too!

并且较少使用块注释而不是嵌套(如果只是因为每个 C 教程都会警告您这一点):

/* you can't nest /* block comments */ these words are not commented */

另一方面,“跳过”预处理器条件“组”内的文本does必须遵守语言的一些规则。标准(C99 §6.10.1p5)的确切措辞是

按顺序检查每个指令的条件。如果其计算结果为假(零),则该组 它控制的内容被跳过:指令仅通过确定的名称进行处理 该指令用于跟踪嵌套条件的级别;剩下的 指令的预处理标记将被忽略,正如指令中的其他预处理标记一样。 团体。

有两个重要的部分。一、正文is标记化,所以它does必须是预处理标记的有效序列。

#if 0
This skipped conditional group doesn't contain a valid sequence of
preprocessing tokens (because of the apostrophe).
#endif

是一个语法错误。

$ gcc -fsyntax-only test.c
test.c:2:37: warning: missing terminating ' character
 this skipped conditional group doesn't contain a valid sequence of
                                     ^

其次,指令仍然被部分处理“以便跟踪嵌套条件的级别”,这意味着您can做这个:

#if 0 // forget this entire mess
    #ifdef __linux__
    do_linux_specific_thing();
    #elif defined __APPLE__
    do_osx_specific_thing();
    #elif defined _WIN32
    do_windows_specific_thing();
    #endif
#endif

and you can’t do this:

    #ifdef __linux__
    do_linux_specific_thing();
    #elif defined __APPLE__
    do_osx_specific_thing();
#if 0 // forget windows
    #elif defined _WIN32
    do_windows_specific_thing();
    #endif
#endif

(最后你不会得到错误,但是......

$ gcc -E -P -U__linux__ -D__APPLE__ -D_WIN32 test.c
    do_osx_specific_thing();
    do_windows_specific_thing();

……我不认为这就是写它的人的本意。)


许多语言指南都会告诉您如何使用#if 0“注释掉”您想要暂时禁用的大块代码区域。他们这么说是因为块注释不能嵌套。如果您尝试使用块注释禁用代码区域,但该区域内有块注释,则注释将提前结束,并且代码可能无法编译。这在 C 没有行注释的时代更为重要;一些项目仅使用行注释进行注释,保留块注释以禁用代码。

但因为里面的代码#if 0#endif仍然是标记化的,并且嵌套预处理器条件仍然必须平衡,您必须小心放置的位置#if 0#endif。这通常不是问题,因为代码在禁用它之前用于编译,因此其中不应该包含任何导致标记化错误的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

#ifdef MACRO 相当于注释吗 的相关文章

  • 如果异常保存在 std::exception_ptr 中,那么在 catch 语句之外使用异常是否安全?

    我有一个std exception ptr其中有一个例外 我要调用std rethrow exception要获取实际的异常 catch 语句之后的异常是否有效 我的猜测是 因为我仍然持有std exception ptr它仍然有效 参见示
  • 如何使用带有进度条的 HttpClient 下载文件?

    我创建了一个名为SiteDownload并添加了一些下载图像的链接 using System Collections Generic using System Linq using System Net using System Threa
  • C++,多语言/本地化支持

    向 C 程序添加多语言支持的最佳方法是什么 如果可能 应该从包含键值对 WelcomeMessage Hello s 之类的纯文本文件中读取语言 我想到了添加一个 localizedString key 函数来返回加载的语言文件的字符串 有
  • TCP客户端;网络流;异步读取; C#

    请原谅我对任务和异步缺乏了解 使用 TcpClient 类 我正在创建与可用服务器的连接 void async RunClientAsync TcpClient client new TcpClient try await client C
  • 委托和接口如何互换使用?

    我可以使用接口方法代替委托吗 如何 我发现搜索接口方法比使用委托更快 我希望有一个简单的代码片段 理论上 可以通过包含单个方法的接口 例如 Java 没有委托 来完成委托完成的所有工作 然而 它使代码变得更加冗长并且没有带来什么好处 话又说
  • lambda 表达式到函数指针的转换

    这是这个问题的后续问题 Lambda 如何作为参数传递 https stackoverflow com questions 3321283 c0x lambda how can i pass as a parameter 据推测 MSDN
  • 运行 C# exe 文件

    复制 为什么我的 NET 应用程序在从网络驱动器运行时会崩溃 https stackoverflow com questions 148879 why does my net application crash when run from
  • 公共领域有哪些替代方案?

    我正在用 java 编写一个游戏 正如问题标题建议的那样 我在类中使用公共字段 暂且 据我所知 公共领域很糟糕 我有一些理解其中的原因 但如果有人能澄清为什么你不应该使用它们 那将不胜感激 问题是 从我所看到的来看 这似乎是合乎逻辑的 是使
  • 将数字 n 拆分为 k 个不同数字的总和

    我有一个数字 n 我必须将它分成 k 个数字 使得所有 k 个数字都是不同的 k 个数字的总和等于 n 并且 k 最大 例如 如果 n 为 9 则答案应为 1 2 6 如果 n 为 15 则答案应为 1 2 3 4 5 这就是我尝试过的 v
  • 如何在 .NET 中自定义 JSON 枚举的反序列化?

    我有以下示例 C 代码 它是使用 svcutil exe 应用程序从 xsd 自动生成的 DataContract public enum Foo EnumMember Value bar Bar 1 EnumMember Value ba
  • 使用 unrar 库 - 将文件提取到文件流缓冲区中

    我需要的是能够将 rar 文件中的文件提取到流中 我正在创建一个测试用例来了解如何使用解压源文件 http www rarlab com rar unrarsrc 3 9 9 tar gz 我已经搜索和修补了一段时间 但我不知道如何使用该库
  • 将数组显式衰减为指针

    最简洁 最惯用的方式是什么明确地将数组衰减为指针 例如 考虑您需要能够指导 SFINAE 或明确过载的情况 template
  • 我的 Opencv 应用程序处理速度非常慢

    我正在构建一个 OpenCV 应用程序 它从相机捕获视频 并在删除背景后将其覆盖在另一个视频上 我无法达到合理的速度 因为它以大约 1 fps 的速度播放输出 而我的背景去除以 3 fps 的速度工作 有没有办法以正常速度显示背景视频并以
  • 使用可变参数模板函数计算多个值的平均值

    我正在尝试编写一个函数来确定任意数量参数的平均值 所有参数都具有相同的类型 出于学习目的 我尝试使用可变参数模板函数来做到这一点 这是我到目前为止所拥有的 template
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 使用 System.Json 迭代 JSON

    我正在探索 NET 4 5 的功能System Json库 但没有太多文档 而且由于流行的 JSON NET 库 搜索起来相当棘手 我基本上想知道 我如何循环一些 JSON 例如 People Simon Age 25 Steve Age
  • 在 C++17 中编译具有非固定基础类型的 constexpr 从 int 静态转换为作用域枚举的未定义行为

    我想知道以下内容是否应该在 C 17 中编译 enum class E A B constexpr E x static cast
  • Lambda 按值捕获和“mutable”关键字

    关键词的必要性mutable在 lambda 中 是造成极大混乱的根源 考虑代码 int x 10 function
  • 定义一个断言,即使定义了 NDEBUG,该断言也有效

    我想定义一个assert与标准相同的宏assert 3 http man7 org linux man pages man3 assert 3 html调用 但它不会被预处理器删除NDEBUG被定义为 这样的呼唤 让我们称之为assert2
  • 具有两个表的谓词构建器

    A Party可以有一个或多个Contact对象 我想选择全部Parties谁的街道名称包含特定关键字 如果我只想搜索Party我可以使用下面的代码 但我如何扩展它来搜索Contact public IQueryable

随机推荐