为什么这个表达式是不合格的?

Lig*_*ica 14 c++ language-lawyer c++11

在x86_64 CentOS 7 GCC 4.8.5 C++ 11上:

#include <iostream>

int main()
{
    std::cout << ((ssize_t)1 - (size_t)5) << '\n';
}

// Output: 18446744073709551612
Run Code Online (Sandbox Code Playgroud)

但:

#include <iostream>

int main()
{
    std::cout << ((ssize_t)1 - (unsigned int)5) << '\n';
}

// Output: -4
Run Code Online (Sandbox Code Playgroud)

在i686 CentOS 6 GCC 4.8.2 C++ 11上,他们都4294967292这样做,所以我必须这样做:

#include <iostream>

int main()
{
    std::cout << ((ssize_t)1 - (ssize_t)5) << '\n';
}

// Output: -4
Run Code Online (Sandbox Code Playgroud)

显然,这是一个非常人为的例子,我理解我在整体推广规则中遵循平台/实现定义的类型等价的各种条款,但在星期四,我的大脑无法解开它们进行严格的评估.

究竟是什么标准规则导致了这些结果?

Col*_*mbo 16

免责声明:我参考C++ 17最新草案N4606第5段第11段.我引用和引用的措辞包含在N3337的第9段中,它实际上与C++ 11标准相同,并且在C++ 14的FD中也是如此,所以这个答案也适用于这些标准.

假设ssize_t并且size_t具有相同的等级,在第一种情况下,[expr] /(11.5.5)适用:

否则,两个操作数都应转换为与带符号整数类型的操作数类型相对应的无符号整数类型.

1将被转换为无符号版本ssize_t,它应该是 size_t-hence无符号下溢,值为2 sizeof(size_t)*8-4.

对于你的第二种情况,假设等级unsigned小于ssize_t,并且后者可以保留所有前者的值; 见[expr] /(11.5.4):

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

5将被转换为ssize_t,所以我们得到阴性结果.如果ssize_t不是等级unsigned,我们得到2 sizeof(unsigned)*8-4; 如果相反ssize_t不能保持所有unsigned的价值,我们再次得到负面结果,因为我们落到前面提到的(11.5.5).