【问题标题】:Is there any difference between 1U and 1 in C?C中的1U和1有什么区别吗?
【发布时间】:2018-04-26 23:47:24
【问题描述】:
    while ((1U << i) < nSize) {
        i++;
    }

使用1U 代替1 有什么特别的原因吗?

【问题讨论】:

  • 这段代码出现在php的源代码中,在文件zend_hash.c中。

标签: c integer


【解决方案1】:

在大多数编译器上,两者都会给出具有相同表示的结果。但是,根据 C 规范,对有符号参数进行位移操作的结果会给出实现定义的结果,因此在 theory1U &lt;&lt; i1 &lt;&lt; i 更可移植。实际上,您会遇到的所有 C 编译器都将有符号左移视为无符号左移。

另一个原因是如果nSize 是无符号的,那么将它与有符号的1 &lt;&lt; i 进行比较将产生编译器警告。将 1 更改为 1U 可以消除警告消息,并且您不必担心如果 i 是 31 或 63 会发生什么。

编译器警告很可能是代码中出现1U 的原因。我建议在打开大多数警告的情况下编译 C,并通过更改代码来消除警告消息。

【讨论】:

  • 1&lt;&lt;i 不是实现定义的。只要值不溢出INT_MAX,它就定义明确,如果溢出(进入符号位)未定义的行为
  • 对不起,你是对的(大部分)。只有当结果不能在结果类型中表示时,它才是未定义的(标准没有提到符号位,但由于今天每个人都使用二进制补码,所以会发生这种情况)。
【解决方案2】:

1U 未签名。它可以携带两倍大的值,但没有负值。

根据环境,使用 U 时,i 最大可以是 31 或 15,而不会导致溢出。如果不使用 U,i 最多可以是 30 或 14。

31, 30 用于 32 位 int
15, 14 用于 16 位 int

【讨论】:

  • 不,它们不一样。 1U
【解决方案3】:

如果 nSize 是一个int,它最大可以是 2147483647 (2^31-1)。如果您使用1 而不是1U,那么1 &lt;&lt; 30 将得到1073741824,1 &lt;&lt; 31 将是-2147483648,因此如果nSize 大于1073741824,则while 循环将永远不会结束。

对于1U &lt;&lt; i1U &lt;&lt; 31 的计算结果为 2147483648,因此您可以安全地将其用于 nSize 高达 2147483647。如果 nSize 是无符号整数,则循环也可能永远不会结束,就像在这种情况下一样nSize 可以大于1U &lt;&lt; 31

编辑:所以我不同意答案告诉你 nSize 应该是无符号的,但如果它是有符号的,那么它不应该是负数......

【讨论】:

    【解决方案4】:

    1U 未签名。

    他们在表达式中使用无符号值的原因是(我猜)因为nSize 也是无符号的,并且编译器(当使用某些参数调用时)在比较有符号和无符号值时会发出警告。

    另一个原因(在我看来不太可能,但如果不知道 nSize 应该假设的 wath 值我们无法知道)是无符号值可能是有符号值的两倍,因此 nSize 可能高达~4*10^9 而不是 ~2*10^9。

    【讨论】:

      猜你喜欢
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 2011-02-27
      • 2016-06-22
      • 2016-04-22
      • 2011-10-24
      • 2018-04-07
      相关资源
      最近更新 更多