使用转换将负整数转换为正整数

Convert negative integer to positive integrer using casting

我想要以下想法:我有 short a = -4; 并且我有一个 unsigned short b = (unsigned short)a; 当我printf("%hu", b)时,为什么不打印4?如何使用转换将负整数转换为正整数?

听起来您想要数字的绝对值,而不是强制转换。在 C 中,我们有 abs / labs / llabs 函数,可在 <stdlib.h>.

中找到

如果您提前知道该值为负数,您也可以直接取反:-a.

shortunsigned short 通常是 16 位整数。因此,签名版本 (short) 的限制是 -32768 到 32767,unsigned short 的限制是 0 到 65535。从有符号转换为无符号仅 wraps 个值,因此 -4 将被转换为 65532.

这是在 C 语言中转换为无符号的方式。

如果您同意使用 additions/substractions,您可以:

65536l - (unsigned short) a

该操作将使用 long 类型(因为有 l 后缀),该类型至少需要 32 位整数类型。这应该成功地将任何负短整数转换为其绝对值。

如果您只想获得绝对值,则应该使用 <stdlib.h> 中的 abs() 函数。

否则,当你进行这样的转换时,你会触发以下来自C17 6.3.1.3的转换规则:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type. 60)

其中脚注 60) 很重要:

  1. The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

数学值意味着我们在计算时不应该考虑环绕等。符号格式(2 的补码等)也无关紧要。应用此规则,则:

  • 您有数学值 -4 并从 signed short 转换为 unsigned short
  • 我们比最大值加一。即 -4 + USHRT_MAX + 1,其中 UINT_MAX 可能是 2^16 = 65535.
  • -4 + 65535 + 1 = 65532。这在新类型 unsigned short.
  • 的范围内
  • 我们第一次尝试就在范围内,但“反复加减”本质上与取模 (max + 1) 的值相同。

此转换定义明确且可移植 - 您将在 short 为 16 位的所有系统上获得相同的结果。