我有以下代码:
#include <cstdint>
template <typename T>
T test(T a, T b)
{
float aabb = reinterpret_cast<float>(a - b);
}
int main(int argc, const char *argv[])
{
std::uint8_t a8, b8;
test(a8, b8);
return 0;
}
我知道reinterpret_cast<float>
无法正常工作,并且在编译时会出错。我正在使用该错误,以便编译器告诉我a - b
的类型。
问题在于,在这种情况下,当a - b
都是int
时,它表示uint8_t (unsigned char)
的类型为uint16_t
。 uint32_t
也是如此。但不是a - b
表示unsigned int
是var subjectID = "foo";
。
所以,我的问题是:这是预期的行为(unsigned char - unsigned char给出一个int),还是这种奇怪的编译器bug(用GCC和clang测试过)?
答案 0 :(得分:11)
是的,这是预期的,作为所谓的通常的算术转换的一部分,结合整数提升的规则。
C ++ 03和C ++ 11之间的确切措辞有所改变,但最终结果在这种情况下是相同的。
[C++03: 4.5/1]:
类型为char
,signed char
,unsigned char
,short int
或无符号short int
的左值可以转换为左值如果int
可以表示源类型的所有值,则输入int;否则,源rvalue可以转换为unsigned int
类型的右值。
[C++03: 4.5/5]:
这些转化称为整体促销。
[C++03: 5/9]:
许多期望算术或枚举类型操作数的二元运算符会以类似的方式引起转换并产生结果类型。目的是产生一个通用类型,它也是结果的类型。此模式称为通常的算术转换,其定义如下:
- 如果任一操作数的类型为
long double
,则另一个操作数应转换为long double
。- 否则,如果任一操作数为
double
,则另一个操作数将转换为double。- 否则,如果任一操作数为
float
,则另一个操作数应转换为float
。- 否则,应对两个操作数执行整数促销(4.5)。 54
- 然后,如果任一操作数为
unsigned long
,则另一个操作数将转换为unsigned long
。- 否则,如果一个操作数是
long int
而另一个unsigned int
,那么如果long int
可以表示unsigned int的所有值,则unsigned int应转换为along int
;否则两个操作数都应转换为无符号long int
。- 否则,如果任一操作数为
long
,则另一个操作数应转换为long
。- 否则,如果任一操作数为
unsigned
,则另一个操作数应转换为unsigned
。[注意:否则,唯一剩下的情况是两个操作数都是
int
]
[C++11: 4.5/1]:
整数转换级别(4.13)小于bool
,char16_t
,char32_t
或wchar_t
的整数类型的prvalue如果int
可以表示源类型的所有值,则int
的等级可以转换为int
类型的prvalue;否则,源prvalue可以转换为unsignedint
类型的prvalue。
[C++11: 4.5/7]:
这些转化称为整体促销。
[C++11: 5.9]:
许多期望算术或枚举类型操作数的二元运算符会以类似的方式引起转换并产生结果类型。目的是产生一个通用类型,它也是结果的类型。此模式称为通常的算术转换,其定义如下:
- 如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果另一个操作数的类型不同,则表达式格式不正确。
- 如果任一操作数的类型为long double,则另一个操作数应转换为long double。
- 否则,如果任一操作数为double,则另一个操作数应转换为double。
- 否则,如果任一操作数为float,则另一操作数应转换为float。
- 否则,应对两个操作数执行整数提升(4.5)。 59 然后,以下规则应适用于提升的操作数:
- 如果两个操作数具有相同的类型,则无需进一步转换。
- 否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有更高等级的操作数类型。
- 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则带有符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型。
- 否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为带有符号整数的操作数的类型类型。
- 否则,两个操作数都应转换为无符号整数类型,对应于带有符号整数类型的操作数类型。