2016-12-01 40 views
14

在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 

极其人为的例子,很明显,我明白,我打依赖于平台/ impleme在积分促销规则不同条款ntation-defined type equivalences,但在星期四我的大脑无法解开它们进行严格的评估。

标准规则的序列究竟是什么使我得到这些结果?

+2

在这两个平台中'sizeof(ssize_t)','sizeof(unsigned int)'和'sizeof(size_t)'怎么样? – max66

+1

给定您获得的值(2^64-1和2^32-1),您可能有'sizeof(sizeize)== sizeof(ssize_t)== 8 sizeof(int)== sizeof(unsigned int)在CentOS 7上是== 4,在CentOS 6上是'sizeof(size_t)== sizeof(ssize_t)== sizeof(int)== sizeof(unsigned int)== 4',所以在后面的例子中'unsigned int '转换成'ssize_t'(相同的大小,无符号的胜利),而在另一个中则得到相反的结果(较大的胜利)。 – Holt

回答

16

免责声明:我参考了最新的C++ 17草案N4606第5条第11款。我引用和引用的措辞包含在paragraph 9 of N3337中,它实际上与C++ 11标准相同,并且在C++ 14的FD中也以这种形式存在,所以这个答案也适用于这些标准。

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

否则,两个操作数应被转换为对应于所述 类型的操作数的无符号整数类型有符号整数类型。

1将被转换为无符号版本的ssize_t,这应该是size_t —因此无符号的下溢,和2 sizeof(size_t)*8 -4的值。

对于第二种情况,假设unsigned的排名小于ssize_t的排名,而后者可以保留前者的所有值;见[expr]/(11.5.4)

否则,如果用符号整型操作数的类型,可以表示所有的 与无符号整数类型的操作数的类型的值的,与无符号整数类型的操作数应当 被转换为带符号整数类型的操作数的类型。

I.e. 5将被转换为ssize_t,所以我们得到否定的结果。如果ssize_t不是比unsigned更高的等级,我们会得到2 sizeof(unsigned)*8-4;如果代替ssize_t无法保持所有的unsigned的值,我们会再次得到否定结果,因为我们会遇到上述(11.5.5)。

相关问题