C++右移、异或问题

C++ Right Shift, XOR problems

我有这个示例代码:

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#ifndef uint32
#define uint32 unsigned long int
#endif
#define L(a) printf("\n%x >> 1 = %x", a, a>>1)
int _tmain(int argc, _TCHAR* argv[])
{
    uint32 a = 2941362065;
    uint32 b = 509727776;
    uint32 c = a ^ b;
    L(a^b);
    printf("\n%x >> 1 = %x", c , c>>1);
    return 0;
}

我的问题是 L(a) returns

b1304bb1 >> 1 = a0617581

同时

printf("\n%x >> 1 = %x", c , c>>1);

returns

b1304bb1 >> 1 = 589825d8

最后一个值似乎与 windows 计算器 returns 一样正确。 此代码在 WinXP 32 上是 运行。有什么想法吗?

L(a^b) becomes printf("\n%x >> 1 = %x", a^b, a^b>>1)

>> 的优先级为 5 而 ^ 为 9(参见 this),这意味着上面的调用给出与以下相同的结果(注意额外的括号):

printf("\n%x >> 1 = %x", a^b, a^(b>>1))

您应该通过在参数周围添加括号来更改 L 定义:

#define L(a) printf("\n%x >> 1 = %x", (a), (a)>>1)

最好使用函数而不是 L 宏。

宏扩展为:

printf("\n%x >> 1 = %x", a ^ b, a ^ b >> 1)

由于 << 的优先级高于 ^(参见 here),它被处理为 a ^ (b >> 1),而不是 (a ^ b) >> 1

您的宏中需要括号:

#define L(a) printf("\n%x >> 1 = %x", (a), (a)>>1)

一般来说,您通常应该将可以是表达式的宏参数括起来。与函数调用不同,宏参数在调用之前不会被计算,它们只是作为文本被替换。这样你就可以轻松得到意想不到的分组。

但更好的指导方针是,当函数也能正常工作时,不要使用宏。

您对 C 中宏的工作方式很感兴趣。右移比 xor 有更高的优先级,所以它会先发生。您应该用括号将 L 定义中 a 的每个实例括起来。