2009-11-03 125 views
10

前些天,I came across该构建体:便携式如何将-1转换为无符号类型?

static_cast<size_type>(-1) 

在一些示例C++代码,这很可能(取决于其中size_type是从细节)是等效于以下C:

(size_t)(-1) 

据我所知,它的工作原理是-1的二进制补码算法的表示为11111...1,因为它具有尽可能多的位数,所以这是一种获得最大值的快速方法,即无符号类型size_t可以容纳。但是,我的理解是,C不保证会使用二进制补码;如果C实现使用补码,那么它将比最大值小1,并且如果它使用符号幅度,它将刚好超过最大值的一半。

是否存在一些我不知道的皱纹,确保这个工作正确无论使用的有符号整数的表示如何? C和C++有什么不同(许多令人惊讶的事情)?

+3

如果你想确定,总是有'std :: numeric_limits :: max()'。 – UncleBens 2009-11-03 15:23:29

+0

我认为这样的情况是为什么你的语言中有static_cast和reinterpret_cast - static_cast可以给你一些可预测的(并且因此有用),但是在某些平台上可能有较慢的实现,而reinterpret_cast可以取消任何保证。 – Kylotan 2009-11-03 15:46:24

+3

这是恕我直言最好的方式来获得所有的比特数。使用'〜0U'的选项也可以工作(如果你忘记添加'U'并执行'〜0',例如所有的比特位都是0),但是使用'-1'转换为'unsigned'类型它始终独立于类型工作。所以你不必关心使用'ULL'或者首先强制转换为'unsigned short' - 你可以使用'-1'并赋值:)参见http://stackoverflow.com/questions/809227/它是安全的 - 使用 - 将所有位设置为真1 – 2009-11-03 15:50:34

回答

19

对无符号算术的要求保证将-1转换为无符号类型将产生目标类型可能的最大数目。 C99,§6.2.5/ 9:“...无法用结果无符号整数类型表示的结果减少的模数大于可由结果类型表示的最大值的数。

这是在C和C相同++(在C++标准,类似的措词在脚注41发现 - 这不是标准化的,但它说明的其它措辞是)。

+6

对于C++,规范性措辞在'4.7/2 ' – 2009-11-03 15:41:09

+0

谢谢!这正是我想知道的皱纹 – Pillsy 2009-11-03 15:53:51

14

要在“安全”方面,并做“正确的”(C++)的方式,值得看的STL:的

std::numeric_limits<size_t>::max() 
+3

唯一的缺点是该值不是一个常量表达式。您可以使用'integral_constant ',但'integral_constant :: max()>'不起作用:( – 2009-11-05 16:21:36

2

如果你正在寻找得到最大(或最小)值一种便携式的某种类型,最好使用如下的标准numeric_limits类。

#include <limits> 

size_type max = std::numeric_limits<size_type>::max() 
size_type min = std::numeric_limits<size_type>::min() 

我怀疑这些函数的某些实现可能会使用您所描述的转换作为平台最优化方式来获取最小值/最大值。

5

“据我所知,它的工作原理是-1表示二进制补码算术......”。

不,它并不是基于这个事实。它基于标准的要求,被转换为N位无符号类型的单值必须产生一个无符号值,它与原始有符号模2^N“相等”。

它必须以这种方式工作,而不管实施使用的签名表示。在2的补码情况下,它本身就是这样工作的,但对于其他表示,编译器将不得不做额外的工作以满足标准要求。

+0

呃......公平:标准的写法正好可以让CPU直接执行2的补码运算,当然不是**不正确**在解释中引用2的补码语言标准的存在是为了满足硬件和用户的需求,而不是相反。 – 2009-11-03 18:51:02

+0

我同意“满足用户的需求”部分。硬件的需求“?No. – AnT 2009-11-03 19:22:47

+0

我之前已经写下了答案,当我读到它们时,”值是'UINT_MAX',因为在二进制补码中'-1'是全位1“。简单地把它倒过来r,我会upvote这个答案。 – 2009-11-03 19:56:28

相关问题