Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 意外的宏观评估_C++_Macros - Fatal编程技术网

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