为什么打印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。
答案 0 :(得分:3)
(§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
;因为整数提升规则。 1
是int
表达式:(uint32_t)0 - 1)
产生的类型为unsigned int
;还是因为usual arithmetic conversions。 unsigned int
被视为大于int