【问题标题】:C/C++ power of two macro两个宏的 C/C++ 幂
【发布时间】:2016-03-10 06:46:43
【问题描述】:

我的二能力不如我应该的那么好,所以我想也许我可以#define 一些东西。

不幸的是,我对预处理器指令非常缺乏经验,而且我无法弄清楚如何执行诸如 for 循环之类的事情。我看了看:

但是他们都没有 for 循环的例子。我想要的只是能够写出pwrtwo(5) 之类的东西,而不是使用计算器算出 25 是 32。

【问题讨论】:

    标签: c++ macros preprocessor-directive


    【解决方案1】:

    为什么不正确地使用函数呢?这甚至允许我们在编译时使用强大的 constexpr 生成结果!

    template <class T>
    constexpr T pwrtwo(T exponent) {
        return (T(1) << exponent);
    }
    

    【讨论】:

    • 您甚至可以将其模板化,这样您也可以将它干净地用于其他整数类型。
    • 返回 T 而不是 int?
    • 这是我不确定的事情:写T(1) 会更好,还是表达式获得右侧的类型?即,如果 T 的类型大于 int1 的类型),这是否正确?
    • @mindriot 强制转换是隐式发生的,但我将它添加到答案中,因为显式强制转换总是更可取
    • 刚刚测试过了。您肯定需要显式转换:ideone.com/z5GGvS - 即使在 64 位系统上您也需要它,因为默认情况下 1 被解释为 有符号 整数。
    【解决方案2】:

    一个答案(不正确)表明答案应该是#define pwrtwo(x) (1 &lt;&lt; ((x) - 1)。然而:

    1 = 0000 0001 二进制模式

    现在,当它要求 2 次方 5 时,然后

    1 ;其中 x = 5

    1 应该移动 4 次然后结果将是

    0001 0000 ==> 2 次方 4

    但这是错误的,这就是为什么实际答案应该是:

    #define pwrtwo(x) (1 << (x))
    

    【讨论】:

      【解决方案3】:

      2x1 &lt;&lt; x,所以:

      #define pwrtwo(x) (1 << (x))
      

      【讨论】:

      • 不是1&lt;&lt;x吗?
      • OKOK,这是漫长的一天。感谢您的更正和编辑。
      【解决方案4】:

      这个宏可以完成这项工作:

      #ifndef PWRTWO
      #define PWRTWO(EXP) (1 << (EXP))
      #endif
      

      但是,建议不要使用它,除非您限制或限制 EXP 的值范围!

      尝试在int 的大小为 4 个字节的机器上将这些值输入到此宏中,尝试编译并运行,然后告诉我每个值会发生什么:

      std::cout << PWRTWO(30) << std::endl; // Okay
      std::cout << PWRTWO(31) << std::endl; // - value
      
      // In the following cout statement within the macro, do not confuse the 
      // (x >= 32) as what is actually being passed into the macro as an argument. 
      // This is just a short hand notation to represent all values >= 32 where the actual
      // numerical value would be entered into this macro statement as there is
      // no defined variable x here in this context nor any comparison expression being passed to it.
      
      // Compiler Warning C4293 '<<' shift count negative or two big, undefined behavoir
      std::cout << PWRTWO(X >= 32) << std::endl; // In most cases on my machine it prints out 0. 
      //However, since this is undefined behavior, there is no telling what it could or may do on another machine.
      

      编辑

      // Try this for loop to see the actual values being printed out as long as 
      // the integer value on your machine is 32bit or 4 bytes in size.
      std::cout << "Excepted values for 32bit integers" << std::endl;
      std::cout << "----------------------------------\n";
      for ( int i = 0; i < 31; i++ ) {
          std::cout << PWRTWO( i ) << std::endl;
      }
      std::cout << std::endl;
      
      // Then print out the next one
      std::cout << "First value to produce a negative result with int being 32bit." << std::endl;
      std::cout << "------------------------------------------\n";
      std::cout << PWRTWO( 31 ) << std::endl << std::endl;
      
      // Then print out these as well : compiler warnings
      std::cout << "Value Range that generates a compiler error." << std::endl;
      std::cout << "-------------------------------------------\n";
      for ( int i = 32; i <= 100; i++ ) {
          std::cout << PWRTWO( i ) << std::endl;
      }
      

      【讨论】:

      • 请注意,最后一个样本 (std::cout &lt;&lt; PWRTWO(X &gt;= 32) &lt;&lt; std::endl;) 将在每台机器上打印 1 或 2(假设 X 在任何地方定义),因为 X &gt;= 32 的计算结果为 0(假)或 1(真) .一个否定的参数将导致未定义的行为,一个大于sizeof(int) * CHAR_BIT 的参数也是如此。
      • @JonathanLeffler 您误解了我使用表达式 (x >= 32) 的意图。它代表输入到宏中的实际值,例如 32、33、34、35 等,而不是实际表达式本身,在我的 windows 7 机器上,它在每种情况下都显示 0 >= 32。我对这种混乱表示歉意,我将编辑并在原始答案中添加评论以反映这一点
      • 为什么投反对票? OP 要求提供#define 或宏!这是两个宏的幂!
      猜你喜欢
      • 2011-01-28
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-28
      • 2018-10-14
      • 2011-01-22
      相关资源
      最近更新 更多