C++ 为什么这个表达式没有签名?

C++ 为什么这个表达式没有签名?,c++,c++11,language-lawyer,C++,C++11,Language Lawyer,在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 很明显,这是一个极为人为的例子,我知道我根据平台/实现定义的类型等价性,在积分提升规则中遇到了各种条款,但在周四,我的大脑无法对它们进行严格的评估 导致

在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
很明显,这是一个极为人为的例子,我知道我根据平台/实现定义的类型等价性,在积分提升规则中遇到了各种条款,但在周四,我的大脑无法对它们进行严格的评估

导致我得出这些结果的标准规则的顺序到底是什么?

免责声明:我指的是C++17最新草案N4606第5条第11段。我引用的措辞包含在中,它实际上与C++11标准相同,在C++14的FD中也是如此,因此这个答案也适用于这些标准

假设
ssize\u t
size\u t
具有相同的等级,在第一种情况下适用:

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

1将转换为无符号版本的
ssize\u t
,该版本应为
size\u t
-因此为无符号下溢,2
sizeof(size\u t)*8的值为-4

对于第二种情况,假设
unsigned
的秩小于
ssize\t
,后者可以保存前者的所有值;见:

否则,如果带符号整数类型的操作数的类型可以表示 无符号整数类型的操作数的类型,无符号整数类型的操作数应为 将转换为带符号整数类型的操作数类型


也就是说,
5
将被转换为
ssize\t
,因此我们得到了否定的结果。如果
ssize\u t
的秩不大于
unsigned
,我们将得到2
sizeof(unsigned)*8
-4;相反,如果
ssize\u t
不能保存所有
无符号的
值,我们会再次得到否定的结果,因为我们遇到了前面提到的(11.5.5)。

那么
sizeof(ssize\u t)
sizeof(unsigned int)
sizeof(size\u t)
在这两个平台上呢?我不是语言律师,而是IIRC,无符号整数可以转换为有符号长整数,因为较大的有符号类型可以保存无符号类型的所有值。但如果大小相同,则未签名者获胜。不知道这是否有助于您在规范中找到所需的内容(我现在没有看到)。给定您获得的值(2^64-1和2^32-1),您可能有
sizeof(size_t)==sizeof(ssize_t)==8>sizeof(int)==sizeof(unsigned int)==4
CentOS 7上的sizeof(size_t)==sizeof(ssize_t)==sizeof(int)==(unsigned int)==4
在CentOS 6上,因此在后一种情况下,
unsigned int
被转换为
ssize\t
(大小相同,无符号赢),而在另一种情况下,则得到相反的结果(大小更大的赢)。@Holt未升级;已转换。@JulianDeclercq这不是拼写错误。
#include <iostream>

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

// Output: -4
#include <iostream>

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

// Output: -4