【问题标题】:Value of a short variable in CC中短变量的值
【发布时间】:2016-07-11 09:43:46
【问题描述】:

我有一个带有简短变量声明的简单程序:

    short int v=0XFFFD;  
    printf("v = %d\n",v);  
    printf("v = %o\n",v);  
    printf("v = %X\n",v);

结果是:

v = -3 ; v = 37777777775 ; v = FFFFFFFD

我不明白如何计算这些值。我知道短变量可以保存-32768和32767之间的值,值0XFFFD会导致溢出,但我不知道如何计算确切的值,在这种情况下为-3。

另外,如果我的声明是 v=0XFFFD 为什么输出 v=%X 是 FFFFFFFD?

【问题讨论】:

  • 请阅读default argument promotions,因为printf是一个variadic函数。
  • 它不会导致溢出,只是分配在解释为有符号时恰好是负值的位模式(我认为..)二进制的恭维(表示负数的常用方法)很容易:翻转所有位并加 1。 0xff 变为 0x00 ,+1 =(负)1。
  • %hd 用于签名short%ho%hx 用于unsigned short

标签: c variables integer-overflow short variable-declaration


【解决方案1】:

首先,short 可以短至 16 位(您的编译器可能就是这种情况)。这意味着65533 无法正确表示,赋值溢出,它会换行到-3(因为short int 是一个有符号短整数)。但你已经知道了。

其次,当作为参数发送到 printf 时,short int 会自动转换为 int,但因为 v 包含 -3,所以这就是发送到 printf 的值。

第三,%o%X 转换需要 unsigned int,这与您提供的不太一样。这意味着未定义的行为(理论上),但在实践中它是完全可以预测的。这意味着 -3 的位模式被解释为一个无符号整数而不是在 32 位机器上恰好是 0xFFFFFFFD

【讨论】:

  • 这段代码没有溢出(有超出范围的赋值,是实现定义的)
  • @M.M 你很可能是正确的,我没有想到这一点。我已删除该评论...
【解决方案2】:

如果在这台机器上 short 是 2 个字节,那么 0x8000 是这个类型持有的最大负值 -32768 的二进制表示。由于事物的设计方式,下一个数字由相应的下一个位模式表示,即:

biggest negative value = 0x8000 = -32768
0x8001 = biggest negative value + 1 = -32767
0xFFFF = biggest negative value  + 0x7FFF = -1
0xFFFE = biggest negative value  + 0x7FFE = 0xFFFF - 1 = -2
0xFFFD = biggest negative value  + 0x7FFD = 0xFFFF - 2 = 0xFFFE - 1 = -3

【讨论】:

    【解决方案3】:

    数字 0xFFFD 不会导致溢出,因为 -3 完全在 -32768 到 32767 的范围内。

    任何短变量都是带符号的二进制补码,-3(十进制)的结果与任何二进制补码值一样计算。因此,要了解如何计算 -3(十进制)的结果,请查看 youtube 上的许多教程或任何相关教科书。

    您的编译器似乎在将数字打印为 int 之前将您的 short 变量隐式类型转换为 int 值。为此,它必须执行所谓的符号扩展,因为它必须从 16 位有符号二进制补码中生成 32 位有符号二进制补码。就像任何十进制数一样,在数字之前有无限数量的零(例如 34 = 0034),在负二进制补码之前有无限数量的 1。因此编译器将最高有效位复制到左侧。从 0xFFFD 中取出 0xFFFFFFFD,从 177775(oct) 中取出 37777777775(oct),即 (00)1 111 111 111 111 101 (bin)。

    希望这些信息对您有所帮助。

    【讨论】:

      【解决方案4】:

      但我不知道如何计算确切的值,在这种情况下为 -3。

      在计算机中表示整数的最常用方法是 2 的补码。

      如果你有一个 n 位整数,你会得到这样的十进制值:

      十进制值 = - bn-12n-1 + bn-22n-2 sup> + ... + b121 + b020 其中 bi 是位数 i 的值。

      在您的情况下,您有一个 16 位变量。十六进制表示为 0xfffd,二进制表示为 1111.1111.1111.1101

      插入公式你会得到:

      十进制值 = - 1*215 + 1*214 + ... + 1*22 + 0*2 1 + 1*20 = - 3

      有关该主题的更多信息,请参阅https://en.wikipedia.org/wiki/Two%27s_complement

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-12-07
        • 2010-09-25
        • 2015-04-10
        • 2012-07-25
        • 2013-02-01
        • 2021-12-25
        • 2017-07-17
        相关资源
        最近更新 更多