意外的宏观评估

时间:2016-10-28 22:13:06

标签: c++ macros

为什么打印ffffffff

#define MYMACRO(n) (((uint16_t)0 - 1) >> (16 - (n)))
std::cout << std::hex << MYMACRO(1);

虽然这会打印1

#define MYMACRO(n) (((uint32_t)0 - 1) >> (32 - (n)))
std::cout << std::hex << MYMACRO(1);

我尝试使用GCC和cpp.sh。

2 个答案:

答案 0 :(得分:3)

解释在type-promotion-in-c

  

(§6.3.1.1布尔,字符和整数):

     

如果int可以表示原始类型的所有值,则该值将转换为int; ......这些被称为整数促销。   所有其他类型都不会被整数促销更改。

因此,对于您的第一个案例,((uint16_t)0 - 1)会转换为int以满足减法需求。因此,右移操作是算术右移而不是逻辑右移。

答案 1 :(得分:1)

Integral Promotions发生在C ++中。尽管如此,实际测试这些表达方式并不是一个坏主意,以了解幕后发生的事情......

#include <typeinfo>
#include <iostream>
#include <boost/type_index.hpp>
using namespace std;

int main(){
#define MYMACRO(n) (((uint16_t)0 - 1) >> (16 - (n)))
    std::cout << std::hex << MYMACRO(1);

    std::cout << "\n-----\n";
#undef MYMACRO
#define MYMACRO(n) (((uint32_t)0 - 1) >> (32 - (n)))
    std::cout << std::hex << MYMACRO(1);

    std::cout << "\n--++++--\n";
    std::cout << boost::typeindex::type_id<decltype((uint16_t)0)>().pretty_name() << std::endl;
    std::cout << boost::typeindex::type_id<decltype((uint16_t)0 - 1)>().pretty_name() << std::endl;    
    std::cout << boost::typeindex::type_id<decltype((uint32_t)0 - 1)>().pretty_name() << std::endl;
}

在我们的情况下,移位运算符之后的表达式的整数类型不相关。从上面的程序输出看Live On Coliru

ffffffff
-----
1
--++++--
unsigned short
int
unsigned int

总结:

  • 子表达式:(uint16_t)0在大多数平台上产生unsigned short 通常

  • 表达式:(uint16_t)0 - 1产生的类型为int;因为整数提升规则。 1int

  • 类型的整数常量
  • 表达式:(uint32_t)0 - 1)产生的类型为unsigned int;还是因为usual arithmetic conversionsunsigned int被视为大于int