C/C++二次幂宏

4

我的二次幂计算能力不如应该,所以我想也许我可以用#define定义一些东西。

不幸的是,当涉及到预处理器指令时,我非常缺乏经验,而且我无法弄清楚如何做像for循环这样的事情。 我查看了:

但它们都没有for循环的示例。 我想要的只是能够写类似于pwrtwo(5)的东西,而不是使用计算器来计算25等于32。

4个回答

22
为什么不做得正确些,使用一个函数呢?这甚至可以让我们使用强大的constexpr在编译时生成结果!
template <class T>
constexpr T pwrtwo(T exponent) {
    return (T(1) << exponent);
}

1
你甚至可以将其模板化,以便在其他整数类型上也可以干净地使用它。 - mindriot
1
返回 T 而不是 int? - Humam Helfawi
1
@mindriot 强制转换是隐式发生的,但我将其添加到答案中,因为显式强制转换始终是首选。 - Jan Hohenheim
1
刚刚测试了一下。你绝对需要显式转换:http://ideone.com/z5GGvS - 即使在64位系统上,因为默认情况下1被解释为有符号整数。 - mindriot
这会影响速度吗?我相当确定这种方法在编译时之前不会开始工作。 - Ace shinigami
显示剩余3条评论

7

有一个答案(错误地)建议答案应该是#define pwrtwo(x) (1 << ((x) - 1)。然而:

1 = 0000 0001(二进制)

现在,当它被问到2的5次方时,然后

1 << (5-1) ; 其中x = 5

1 应该被移位4次,然后结果将是

0001 0000 ==> 2的4次方

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

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

当然!我需要类似于C的东西,所以 https://dev59.com/R5Tfa4cB1Zd3GeqPXez_#35909762 的 constexpr C++ 方法对我不起作用,但这个位移方法非常完美。谢谢! - Spastika

4

2x1 << x,因此:

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

11
1<<x,对吗? - PeterT
好的好的,今天是个漫长的一天。感谢您的修正和编辑。 - user207421

3
这个宏可以完成这项任务:
#ifndef PWRTWO
#define PWRTWO(EXP) (1 << (EXP))
#endif

然而,如果您不限制或限定EXP的值范围,则最好不要使用它!请尝试在一个整数大小为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;
}

1
请注意,最后一个示例(std::cout << PWRTWO(X >= 32) << std::endl;)将在每台机器上打印出1或2(假设X在任何地方都有定义),因为X>=32会评估为0(false)或1(true)。负参数将导致未定义的行为,大于sizeof(int)*CHAR_BIT的参数也是如此。 - Jonathan Leffler
@JonathanLeffler 您误解了我使用表达式 (x >= 32) 的意图。它的意思是代表实际输入到宏中的值,例如32、33、34、35等,而不是表达式本身,而且在我的Windows 7机器上,在每个 >= 32 的情况下都显示为0。对于这种混淆我感到抱歉,我将编辑并添加评论到原始回答中以反映这一点。 - Francis Cugler
为什么要踩这个问题?OP 请求一个 #define 或者宏!而且这是一个二次幂的宏! - Francis Cugler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接