首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >16位整型计算机和32位整型计算机在减法中的结果不同

16位整型计算机和32位整型计算机在减法中的结果不同
EN

Stack Overflow用户
提问于 2017-05-20 10:23:31
回答 2查看 945关注 0票数 2

当在像MSP430微控制器这样的16位整数机器上运行下面的代码时,s32产生65446

代码语言:javascript
复制
#include <stdint.h>

uint16_t   u16c;
int32_t    s32;

int main()
{
    u16c = 100U;
    s32  = 10 - u16c;
}

我的理解是10 - u16c得到了无符号整数的隐式类型提升。数学上,10 - u16c等于-90。但是,如何将负数表示为无符号整型呢?

当-90被提升为unsigned int时,是否意味着忽略了数字的符号?

假设一个数字的符号被忽略。

90的二进制表示是00000000 01011010。当它被赋值给32位宽的有符号整数变量s32时,转换是如何发生的?

为了使s32等于65446,90必须取2的补码。那应该是00000000 10100110

我对理解s32成为65446的过程没有信心。

在32位宽整数机器中,如ARM correct,s32为-90,这是正确的。

要解决16位整数机器中的这种情况,需要为u16c进行(int16_t)的类型转换。这如何解决这个问题呢?

添加了s32的十六进制数据表示,如IAR Workbench (右下角)所示。结果表明,s32变成了0x0000FFA6。因此对于MSP430,从无符号16位转换到有符号32位的机器实现,它只是在前面加上16个0位。

EN

回答 2

Stack Overflow用户

发布于 2017-05-20 11:02:47

代码语言:javascript
复制
100 = 0x0064
0x000A - 0x0064 =
0x000A + 0xFF9B + 1 = 
0xFFA6 = 65446.

请注意,上面的内容既不是有符号的,也不是无符号的,加法和减法对这些事情都是盲目的。现在16位数学运算已经完成,可以使用符号扩展将其提升为0xFFFFF9B。在0xFF9B和0xFFFFF9B两种情况下,如果将这些位解释为有符号,则答案是-90,如果将这些位解释为无符号,则一个是65446,另一个是4294967206。

看看这个:

代码语言:javascript
复制
#include <stdio.h>

int main()
{
    unsigned int ra,rb;

    ra=0x00000005;
    for(rb=0;rb<10;rb++)
    {
        ra--;
        printf("0x%08X\n",ra);
    }
    return(0);
}

你明白了吗?

代码语言:javascript
复制
0x00000004
0x00000003
0x00000002
0x00000001
0x00000000
0xFFFFFFFF
0xFFFFFFFE
0xFFFFFFFD
0xFFFFFFFC
0xFFFFFFFB

这正是你所期望的,你从所有的0中减去1,得到所有的1,与有符号或无符号无关。从10中减去100就相当于循环100次。

你是否期望看到:

代码语言:javascript
复制
0x00000004
0x00000003
0x00000002
0x00000001
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000

对于上面的程序?这是准确的吗?这有意义吗?不是的。

代码中唯一令人好奇的部分是:

代码语言:javascript
复制
s32  = 0xFFA6;

现在,实际上评论中的人可以直接加入,但是标准是说你的u16c从无签名(0x0064)转换到有签名(0x0064),还是它保持无签名而10 (0x000A)被认为是无签名的?基本上我们得到0x000A - 0x0064 = 0xFFA6作为有符号的数学或无符号的(我猜是无符号的,因为在那个操作中声明的一个东西是无符号的)。然后无符号位模式升级为有符号位模式,你采用16位模式,并将其符号扩展到32位0xFFA6变成0xFFFFFFA6,这是我在桌面linux机器上和gcc得到的……

票数 3
EN

Stack Overflow用户

发布于 2017-05-22 16:21:17

简短的回答:

如果整数常量类型为int.

  • If
  • 16位,则不会发生整数提升,此时s32的类型与10的整数常量无关。通常的算术转换将10操作数转换为uint16_t类型(无符号整数)。该运算在16位无符号类型上执行。
  • 未签名环绕提供了10u - 100u = 65445u。= 0xFFA5。这个结果可以放在int32_t中。二的补码不适用,因为运算中涉及的类型是无符号的。
  • 如果int是32位,则参数u16c是整数提升为类型int。不会发生进一步的人工转换,因为在整数提升之后,两个操作数都是int类型。该运算在32位带符号类型上执行,结果为-90.

可移植的代码应该写成:

代码语言:javascript
复制
10 - (int32_t)u16c; // signed arithmetic intended

或as

代码语言:javascript
复制
10u - u16c; // unsigned wrap-around intended
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44081308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档