C++ 意外的宏观评估
为什么要打印C++ 意外的宏观评估,c++,macros,C++,Macros,为什么要打印ffffffff #define MYMACRO(n) (((uint16_t)0 - 1) >> (16 - (n))) std::cout << std::hex << MYMACRO(1); 我用GCC和cpp.sh试过了。中有解释 (§6.3.1.1布尔值、字符和整数): 如果int可以表示原始类型的所有值,则该值将转换为int。。。这些被称为整数促销。 所有其他类型均不受整数升迁的影响 因此,对于第一种情况,((uint16_t)0-1
ffffffff
#define MYMACRO(n) (((uint16_t)0 - 1) >> (16 - (n)))
std::cout << std::hex << MYMACRO(1);
我用GCC和cpp.sh试过了。中有解释
(§6.3.1.1布尔值、字符和整数):
如果int可以表示原始类型的所有值,则该值将转换为int。。。这些被称为整数促销。
所有其他类型均不受整数升迁的影响
因此,对于第一种情况,((uint16_t)0-1)
被转换为int
,以满足减法的需要。因此,右移操作是算术右移而不是逻辑右移。在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;
}
总结如下:
- 子表达式:
像在大多数平台上一样,生成一个(uint16_t)0
无符号的short
- 表达式:
产生一种类型的(uint16_t)0-1
;因为整数提升规则int
是类型为1
int
- 表达式:
产生一种类型的(uint32_t)0-1)
;还是因为。无符号int
被视为大于unsigned int
int
uint16\u t
被提升为int
(正好是32位)。这是因为1的类型为int
。关键是,在您的平台上,int
是一个比uint16\u t
更大/更宽的整数类型。有没有办法在uint16\u t中进行此计算,同时获得预期的1?是:也将1
转换为uint16\u t
。@user268396:不会有任何区别。@Silicomancer:不可能在中进行计算uint16\u t
。无论您做什么,计算本身都将在int
中完成。您可以做的是在减法后强制将结果返回到uint16\t
。即使在这之后,它也会提升回int
,但至少不会降到负值区域。例如,使用((uint16_t)(0-1)>(16-(n)))
,这与((uint16_t)-1>(16-(n))相同。或者,更好的是,((uint16_t)((uint16_t)-1>>(16-(n)))
@AnT可以强制转换为无符号int
,而不是让编译器升级为int
,以获得所需的行为。有没有办法在uint16_t中进行此计算,同时获得预期的1?@Silicomancer,是的,您可以。。。。将整个表达式强制转换为类型uint16\u t
。。。。通过这样定义宏:<代码> M.M定义MyAcMro(n)((UTI1616T)((UTI1616T)((UTI1616)0(1))>(16(n)))< /Cord> @,通过“C++表达式的结果类型可以不同于一个子表达式到它的封闭表达式”——我从孤立的处理子表达式的观点出发。例如,游戏中也有一些有趣的规则。。。孤立地对待子表达式是错误的吗?尽管如此,我还是删除了该声明。@M.M,谢谢。修正了最后的要点。。。我也在学习。:-。你能回答我在前面评论中的问题吗?Thanks@WhiZTiMC和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;
}
ffffffff
-----
1
--++++--
unsigned short
int
unsigned int