为什么这种表达未签名

Why is this expression being unsigneded?

本文关键字:为什么      更新时间:2023-10-16

on 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

但是:

#include <iostream>
int main()
{
    std::cout << ((ssize_t)1 - (unsigned int)5) << 'n';
}
// Output: -4

和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

显然,一个极为人为的例子,我知道我根据平台/实施定义的等价符合整体促销规则的各个条款评估。

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

免责声明:我是指C 17的最新N4606草案第5条第11段。我引用和引用的措辞包含在N3337的第9段中,该段实际上与C 11标准相同,并且在C 14的FD中也以该形式相同,因此此答案也适用于这些标准。

假设ssize_tsize_t的等级相等,在您的第一种情况下,[Expr]/(11.5.5)适用:

否则,两个操作数应转换为对应于该的无符号整数类型 具有签名整数类型的操作数类型。

1将转换为 ssize_t的无符号版本,因此应为 size_t&mdash;因此,无符号的下流流量,值为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)。