【问题标题】:short int Integer wrap around / short int inversion in c not understood, difference between assignment and printsshort int Integer wrap around / short int inversion in c 不理解,赋值和打印之间的区别
【发布时间】:2017-07-30 18:55:15
【问题描述】:

以下代码片段

short int k = -32768;
printf("%d \n", -k);
k=-k;
printf("%d \n", k);

打印

32768 
-32768

我会假设两个打印件是相等的。 有人能解释一下区别是什么以及为什么分配k=-k 会导致回绕吗?在网上很难找到解释,因为我真的不知道该用谷歌搜索什么。

【问题讨论】:

  • 整数促销再次来袭。

标签: c types integer integer-overflow


【解决方案1】:

因为SHRT_MIN = -32768SHRT_MAX = +32767。看看 2 的补码是如何工作的。

编辑

实际上,根据 C 编程语言的国际标准(即Committee Draft — May 6, 2005,第 50-51 页)关于有符号整数:

对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。

不需要任何填充位;应该只有一个符号位。

作为值位的每个位应与对应无符号类型的对象表示中的相同位具有相同的值(如果有符号类型中有 M 个值位,无符号类型中有 N 个值位,则 M

如果符号位为零,则不会影响结果值。

如果符号位为1,则通过以下方式之一修改该值:

  • 符号位为0的对应值取反(符号和幅度);

  • 符号位的值为 -(2N)(二进制补码);

  • 符号位的值为 -(2N - 1)(反码)。

其中哪一个适用于实现定义,无论是符号位为 1 且所有值位为零(前两位)的值,还是符号位和所有值位为 1 的值(对于一个的补码),是陷阱表示或正常值。在符号和幅度以及反码的情况下,如果这种表示是正常值,则称为负零。

因此,换句话说,在您的情况下,似乎使用了 2 的补码,但不应假定所有平台和编译器都使用这种补码。

【讨论】:

  • 为什么打印和赋值不同,如果我只是打印-k而不是像上面那样分配它时不会发生环绕
  • @FalcoWinkler 我猜在打印中这个数字被解释为一个整数(不是短的)。
  • @FalcoWinkler k=-k; 什么都不做,因为32768 不能由short 表示。超出范围。
  • @WeatherVane 当然它会做一些事情,它将 32768 分配给 k,它环绕到 -32768。您的评论说,每次您分配无法表示的内容时,分配都不会执行?错了
  • 那你为什么要问一个你知道答案的问题?我的意思是 k 没有改变,因此它什么也不做。永远不会有 k == 32768 然后“换行”的点。
【解决方案2】:

-32768 是十六进制的800032768 不能表示为带符号的 16 位数字,因此编译器将 -k 提升为具有十六进制值 00008000int。当这个数字分配给 16 位变量时,高位被截断,导致8000-32768 再次出现。

【讨论】:

    【解决方案3】:

    好吧,要打印 short,您需要使用长度修饰符。

    将格式字符串更改为%hd

    【讨论】:

    • 所以确切的答案是:%d 将变量视为整数,因此不会发生回绕。作业将其视为简短,从而导致回绕。使用 %hd 时,print 也将 k 视为 short,我们得到相同的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 2012-08-30
    • 1970-01-01
    • 2011-10-05
    • 2021-12-13
    • 1970-01-01
    • 2011-08-11
    相关资源
    最近更新 更多