uint8_t 和 int8_t 转换

p21*_*esk 0 c++ type-conversion

考虑以下程序:

using namespace std;

int main()
{
    uint8_t b = 150;
    int8_t a = -10;
    
    if (a>b){
        cout << "greater" << endl;
    }
    else{
        cout << "less" << endl; 
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在线 C++14 编译器中,它打印less. 我在使用 x86-64 gcc 12.2 的编译器资源管理器中得到相同的结果

根据文档

否则,操作数具有整数类型(因为此时升级了 bool、char、char8_t、(C++20 起) char16_t、char32_t、wchar_t 和无作用域枚举)产生普通类型,如下:

  1. 如果两个操作数均带符号或均无符号,则具有较小转换等级的操作数将转换为具有较大整数转换等级的操作数。
  2. 否则,如果无符号操作数的转换等级大于或等于有符号操作数的转换等级,则有符号操作数将转换为无符号操作数的类型。
  3. 否则,如果有符号操作数的类型可以表示无符号操作数的所有值,则无符号操作数将转换为有符号操作数的类型。
  4. 否则,两个操作数都将转换为有符号操作数类型的无符号对应项。

在使用 x86-64 gcc 12.2 的编译器资源管理器中,我对其进行了编译并得到以下结果:

.LC0:
        .string "greater"
.LC1:
        .string "less"
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     BYTE PTR [rbp-1], -106
        mov     BYTE PTR [rbp-2], -10
        movsx   edx, BYTE PTR [rbp-2]
        movzx   eax, BYTE PTR [rbp-1]
        cmp     edx, eax
        jle     .L2
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
        mov     esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
        jmp     .L3
...
Run Code Online (Sandbox Code Playgroud)

所以,根据

mov     BYTE PTR [rbp-1], -106
mov     BYTE PTR [rbp-2], -10

Run Code Online (Sandbox Code Playgroud)

uint8_t b被转换为int8_t并被赋值为-106,这似乎是正确的,因为它属于文档的第 3. 点:

否则,如果有符号操作数的类型可以表示无符号操作数的所有值,则无符号操作数将转换为有符号操作数的类型。

如果我正确理解了文档和汇编代码,那么比较

(a>b) //-10 > -106 
Run Code Online (Sandbox Code Playgroud)

应该返回 true。但显然,它返回 false,因为我得到了分支的输出else

所以我的问题是:为什么(a>b)在这个例子中 return false ?

Kam*_*Cuk 5

您忘记了积分促销。来自https://en.cppreference.com/w/cpp/language/operator_arithmetic

如果传递给算术运算符的操作数是整型或无范围枚举类型,则在任何其他操作之前(但在左值到右值转换之后,如果适用),操作数会进行整型提升。

来自https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion

小整型类型(例如 char)的纯右值可以转换为较大整型类型(例如 int)的纯右值

ab首先提升为int,然后进行比较。作为一个int.