【问题标题】:Simple ways to disable parts of code禁用部分代码的简单方法
【发布时间】:2018-04-19 19:35:23
【问题描述】:

这不是解决特定问题的典型问题,而是一种大脑锻炼,但我想知道是否有人有解决方案。

在开发中,我们经常需要禁用或切换部分代码来检查不同的方法。为此,我们使用 cmets 或 #defines,但我最喜欢的是:

//*
[code here]
//*/

现在,当您仅删除第一个斜杠时,代码将被注释掉。

问题:有没有办法实现类似的if-else代码切换?我试图找到它,但我总是遇到一些问题并且找不到有效的解决方案。

也许你知道任何类似的技巧?

【问题讨论】:

  • 使用 cmets 会有问题,因为 cmets 不能嵌套。如果您在禁用的代码中有 cmets,那将无法正常工作。
  • 好点约阿希姆。但是当你在原型制作过程中使用它时,你并没有那么多使用 cmets。
  • 啊,不,但另一方面,原本应该只是原型的代码往往会在现实世界中过于频繁地潜入实际代码。

标签: c++ c


【解决方案1】:

使用#if 0 包装代码可以解决问题,但您仍然需要编辑代码以启用/禁用它。这并不比只使用评论块好多少。

请注意,您也可以使用已定义的预处理器常量:

#ifdef ENABLE_TESTS
// code that you want to run ONLY during tests 
#endif

现在在构建代码时,您可以在构建过程中选择性地定义/取消定义这个常量 - IDE/makefile/build script/command-line - 而无需编辑代码:

$ gcc -DENABLE_TESTS source.c

我添加了这个答案来平衡所有早期的 #if 0 答案,但是这个来自已接受答案的结构是对特定问题的最佳答案/**/ foo(); /*/ bar(); /**/。请谨慎使用此类评论技巧。

【讨论】:

  • 这个名字听起来有点混乱。我希望使用-DDISABLE_TEST 进行编译以禁用测试代码。在这里它启用它。
  • @ArjunShankar 是的,这令人困惑
  • 是的,这样更好。这是一个有用的答案。 +1。
  • 在 java 中有没有这么简洁的东西?
  • @LightyearBuzz 在 java 中没有预处理器,没有。但是java 确实 有一个类似的-D 命令行开关,允许您在命令行上传递System 属性值。您需要使用标准运行时if/then 测试,例如:if (System.getProperty("key", "defaultValue"))。 C #if/#endifcompile-time.
【解决方案2】:
#if 0
...disabled code here
#endif

【讨论】:

  • 使用#if 0 表示禁用代码,#if 01 表示启用允许通过键入单个字符(删除或 1)而不是两个字符(删除和新值)在两种情况之间切换)。
【解决方案3】:

我不确定我是否应该发布此内容,因为我认为这不是“好代码”,但我承认我曾使用以下技术作为快速切换的快速方法当我只是检查一些东西时,有两个小的 sn-ps 代码:

// in the following , foo() is active:
/**/ foo(); /*/ bar(); /**/

现在只需删除前面的星号之一:

// now bar() is active:
/*/ foo(); /*/ bar(); /**/

当然,这不应该超过“只是检查”阶段......

【讨论】:

  • @kolenda: #if 0#else 做同样的事情,而且更干净......
【解决方案4】:

预处理器 if-else 也可以工作

#if 1
  // ... enabled if 1
#else
  // ... enabled if 0
#endif

【讨论】:

    【解决方案5】:

    在这里使用一些预处理器逻辑来帮助你:

    #if 0
        //code goes here
    #endif
    

    享受

    【讨论】:

      【解决方案6】:

      有时我使用下面的技巧在两个 lazy cmets 之间切换。

      //* <-- remove the first slash
      [code block 1]
      /*/
      [code block 2]
      //*/
      

      【讨论】:

        【解决方案7】:

        好吧,如果代码在最终确定之前需要禁用一次两次,我更喜欢使用 IDE 提供的热键来注释掉该代码,然后再注释是的,我需要先选择代码块,但我不想在每次需要禁用部分代码时再包含一个调试变量/预处理器指令/if 语句。大部分时间都是这样。

        另一方面,如果我需要在 2 个代码块之间反复切换以找到正确的东西,那么我使用 if (0) / if (1) 来禁用/启用代码块。

        [code block 1]
        

        稍后

        if (0)
        {
            [code block 1]
        }
        else
        {
            [code block 2]
        }
        

        【讨论】:

        • +1,因为使用您的语法,仍会检查未执行的代码是否存在语法错误,而 #ifdef(s) 会对编译器隐藏该代码。
        • 如果在大循环中,它仍然会受到速度的影响
        【解决方案8】:

        如果您在编译时进行检查,则可以使用 Gigi 的答案,这将有条件地不编译代码段。请注意,预处理器不了解变量、sizeof 或编译器处理的其他内容(因此使用 4 == sizeof(int) 之类的东西不会飞)

        如果你想编译一些不应该运行的调试代码,你可以使用常规的条件语句,比如

        bool debugging = false;
        
        // banana banana banana
        
        if (debugging)
        {
            // do a bunch of stuff here
        }
        

        然后您可以使用调试器通过将 debugging 分配为 true 来访问跳过的部分。

        【讨论】:

          【解决方案9】:

          宏是做到这一点的方法..

          #define COMPILE 
          
          #ifdef COMPILE
          
          //code to comment begins
          cout<<"ha ha ha"<<endl;
          //code to comment ends 
          
          #endif
          

          要禁用代码,只需注释掉#define compile line

          【讨论】:

          • 更明确地说,您可以使用-DCOMPILE 在编译时启用/禁用块,而不必担心开头的#define 子句。
          【解决方案10】:

          有时也需要同步打开/关闭分散在程序中的代码块。

          earlier post by Graham 的启发,我做了这样的事情:

          void doNothing(){}
          #define DO_IF(flag, code) flag ? code : doNothing();
          

          这可以例如如下使用:

          DO_IF(collectStats, recordStats());
          DO_IF(collectStats, store(pullStat()));
          

          一个更好的:

          #define DO_IF(flag,code) if( flag ) { code; }
          

          【讨论】:

          • 这个解决方案比投票最多的解决方案干净得多。你拯救了我的一天!
          【解决方案11】:
          1 ? foo() : bar();
          

          这会执行foo()。将1 更改为0 以改为执行bar()

          与涉及预处理器指令或 cmets 的建议不同,这两个可能的分支都已编译,因此您可以充分利用编译器的语法检查。

          【讨论】:

            【解决方案12】:

            有时我会使用这种方法来避免因 if-endif 定义的无限序列而使代码过度膨胀。

            debug.hpp

            #ifdef _DEBUG
                #define IF_DEBUG(x) if(x)
            #else
                #define IF_DEBUG(x) if(false)
            #endif
            

            example.cpp

            #include "debug.hpp"
            
            int a,b, ... ,z;
            
            ...
            
            IF_DEBUG(... regular_expression_here_with_a_b_z ...) {
                // set of asserts
                assert(... a ...);
                assert(... b ...);
                ...
                assert(... z ...);
            }
            

            这并不总是有效的,因为编译器可能会警告您在此类禁用的代码块中使用了未使用的变量。但至少它具有更好的可读性,并且可以抑制未使用的变量警告,例如:

            IF_DEBUG(... regular_expression_here_with_a_b_z ...) {
                // set of asserts
                assert(... a ...);
                assert(... b ...);
                ...
                assert(... z ...);
            }
            else {
                (void)a;
                (void)b;
                ....
                (void)z;
            }
            

            这并不总是一个好主意,但至少有助于重组代码。

            【讨论】:

              【解决方案13】:

              下面的逻辑应该包含最简单的方法

              if(isMode1)
              {
                  //Code for mode1
              }
              else
              {
                  //Code for other modes
              }
              

              虽然我认为正确的方法是使用PreProcessor Directives

              【讨论】:

                【解决方案14】:

                在我的代码中,我喜欢在我的 main.cpp 文件中执行此操作:

                #define CRAZY_EXPERIMENT
                
                #ifdef TEST
                #include "Test.h"
                #elif ANOTHER_TEST
                #include "AnotherTest.h"
                #elif CRAZY_EXPERIMENT
                #include "CrazyExperiment.h"
                #else
                
                int main(int argc, int * argv[]){
                    runTheProgramLikeNormal();
                }
                
                #endif
                

                您看到的所有头文件都包含自己的main()。根据第一个#define 中定义的内容,程序中只有一个 main() 函数。如果该语句被完全省略,它默认为您看到的规范 main() 函数。

                这使得为我的程序编写仅关注一两个组件的测试变得容易。最好的部分是测试标头与我的代码完全隔离,因此不会错误地留下(甚至链接)测试代码。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-10-10
                  • 2013-10-11
                  • 1970-01-01
                  • 2016-12-23
                  • 1970-01-01
                  • 2022-11-18
                  • 1970-01-01
                  • 2019-02-24
                  相关资源
                  最近更新 更多