【问题标题】:C unsigned int x = 1; smaller than int y = -1; [duplicate]C 无符号整数 x = 1;小于 int y = -1; [复制]
【发布时间】:2017-11-09 01:55:00
【问题描述】:

我确实知道有符号无符号等的区别。 但我不明白以下代码:

unsigned int x = 1;
int y = -1;
    if(y < x)
        printf("of course it is");
    else
        printf("strange stuff");

1 应该大于 -1,无论使用哪种表示。因为控制台会显示“奇怪的东西”。

【问题讨论】:

  • 运算符 (
  • ISO/IEC 9899:2011 (C) §6.5.8 Relational operators -1202 如果两个操作数都具有算术类型,则执行通常的算术转换。两个操作数都将被强制转换为 unsigned int,而在二进制补码中,unsigned int y = -1; // = 4294967296 = 2^32 since integers are 32-bit. 因此您正在比较 4294967296 &lt; 1 这是错误的。
  • 这解释了结果。但是为什么将 y 转换为 unsigned int。为了匹配类型,x 可以转换为 Two´s Complement。

标签: c


【解决方案1】:

有符号的 1(作为字节)以位为单位:00000001

无符号 1 位:00000001

有符号的 -1 位:10000001(或 1 1111111,只是细节)

无符号 -1 位:无有效表示(10000001 为 129)

如果您想安全地比较有符号和无符号变量,您有两种方法:

1) 考虑符号并手动比较它们(例如isSignedLess = (signed &lt; 0) || ((unsigned &lt;= max_signed) &amp;&amp; (signed &lt; unsigned))

2) 将两者都转换为更大的singed(即signed long long)并比较它们(signed long long 可以存储所有有符号/无符号整数的音调)


正如您在 cmets 中看到的,这两种方式都有些棘手。只是不要在任何地方混合签名和未签名。这在 99% 的情况下是可能的。在最后 1% 的情况下,你真的需要知道你在做什么(例如,经常不得不使用带符号的索引和向量,但是 size() - 无符号,所以我问自己一百次“这个向量能达到 MAX_INT 吗?我要做吗?更复杂的代码还是可以完成这项任务?”)。

【讨论】:

  • isSignedLess = (signed &lt; 0) || ((unsigned &lt;= max_signed) &amp;&amp; (signed &lt; unsigned)) 是正确的想法,但可以简化。 isSignedLess = (signed_a &lt; 0) || (signed_a &lt; unsigned_b);。转换为更大的 `signed 并不总是可能的,因为可能不存在更广泛的有符号类型。
  • 首先,正如已经说过的,不建议混合签名和未签名。我只是写了一个有点hacky的解决方法。其次,signed_a &lt; unsigned_b 可能会导致同样的问题,如果编译器决定将 unsigned 截断为有符号(是的,“标准说法......”......我不喜欢记住微小的细节,如果有简单明了的代码)
  • “如果编译器决定将无符号截断为有符号”在 C 中不会发生。
  • 这是 UV-ed,因为它不会警告“混合签名和未签名”。相反,它解决了 OP 与 #1 相比如何处理混合符号的问题。
  • 第二次查看 isSignedLess = (signed &lt; 0) || ((unsigned &lt;= max_signed) &amp;&amp; (signed &lt; unsigned))) 是错误的。 (unsigned &lt;= max_signed) 错误地导致与 unsigned int x = UINT_MAX; int y = 0; 的错误比较失败。
【解决方案2】:

您将无符号整数与有符号整数进行比较。你不应该那样做。 C 通过将其中一个转换为另一个的类型来解决此问题。在这种情况下,它可能会将 y 转换为无符号整数,使其为正数,因此 x 应该与 y 相同。

您可以将它们都设为 int,或者如果确实有必要,您可以在比较时将 unsigned int 转换为 int。

if(y&lt;(int)x)

【讨论】:

  • 其实按照C标准,转换总是到有符号类型,变成无符号类型。
  • if(y&lt;(int)x) 将问题转移到其他对,例如unsigned int x = INT_MAX + 2u; int y = 0;
猜你喜欢
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多