16位int机器(MSP430)和32位int机器(ARM CORTEX)的减法结果不同

Ngu*_* al 2 c embedded arm msp430 cortex-m

当下面的代码针对像MSP430微控制器这样的16位整数机运行时,s32得到65446.

#include <stdint.h>

uint16_t   u16c;
int32_t    s32;

int main()
{
    u16c = 100U;
    s32  = 10 - u16c;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是10 - u16c获取unsigned int的隐式类型提升.数学上10 - u16c等于-90.但是如何将负数表示为unsigned int呢?当-90被提升为unsigned int时,是否意味着忽略了数字的符号?

让我们假设,数字的符号被忽略.
90的二进制表示是00000000 01011010.当这被分配给s3232位宽的有符号整数变量时,转换是如何发生的?

为了s32等于65446,90必须采用2的补码.那就是00000000 10100110.

我不了解s32成为65446 的过程.

在像ARM这样的32位宽整数机器中,s32是-90,这是正确的.

要修复在16位整型机这种情况下,需要的类型转换(int16_t)u16c.这是如何解决这个问题的?

添加s32了IAR Workbench(右下角)所示的hexa数据表示.它显示s32成为0x0000FFA6.因此,对于MSP430,从无符号16位转换为带符号32位的机器实现,它只是预先设置16 0位.

在此输入图像描述

aut*_*tic 5

我的理解是10-u16c获取隐式类型促销unsigned int.

这取决于10((int原样)类型的表示.对于某些系统,您的理解是正确的,我们将首先介绍这一点,但正如您稍后将在本答案中看到的那样,您错过了大部分图片.

第5.2.4节,环境限制规定类型的值int可以在-32767到32767之间; 此范围可以由实现自行决定,但int必须能够代表此范围.

uint16_t但是,如果它存在(它不是必需的)的范围是0到65535.实现不能扩展它; 要求范围是精确的 [0..65535](因此不需要存在这种类型的原因).

第6.3.1.3节,有符号和无符号整数告诉我们来回转换.我不能更好地解释它,所以这是一个直接的引用:

1当具有整数类型的值转换为除_Bool之外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变.

2否则,如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.60)

3否则,新类型已签名且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号.

这一切都支持你的理论,即int值10将被转换为uint16_t if和only,如果 int是16位类型.然而,部分6.3.1.8,正常的算术转换规则应适用第一个决定哪些上述三个转换的发生,因为这些规则改变的方式,你将看到转换时int比十六位更大:

如果两个操作数具有相同的类型,则不需要进一步转换.

否则,如果两个操作数都具有有符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数将转换为具有更高等级的操作数的类型.

否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则具有有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型.

否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数类型的操作数的类型.

否则,两个操作数都转换为无符号整数类型,对应于带有符号整数类型的操作数的类型.


因此,正如您所看到的,表达式的类型10-u16c可能因系统而异.在int16位的系统上,该表达式将是a uint16_t.

数学上10-u16c等于-90.但是如何将负数表示为unsigned int呢?当-90被提升为unsigned int时,是否意味着忽略了数字的符号?

根据附件H.2.2:

在LIA-1意义上,C的无符号整数类型是'modulo',因为溢出或越界结果会静默地换行.

换句话说,如果10转换为a uint16_t并执行减法,则结果将是一个数字,在这种情况下,您可以通过显式转换两个操作数(即将它们转换为)来查看该数字uint16_t.你可以通过使用无符号整数常量来看到类似的效果-90U.这在很大程度上受到前面6.3.1.3引用的规则#2的支持.


当这被分配给32位宽的有符号整数变量s32时,转换是如何发生的?

表达式10-u16c根据6.3.1.3中的规则#1(上面引用)转换为int32_t值并存储为该值.


要修复在16位整型机这种情况下,需要的类型转换(int16_t)u16c.这是如何解决这个问题的?

类型转换没有为此讨论添加有用的信息.也许您正在使用不合规(错误)编译器.我怀疑手册可能会对此有所了解,但由于我不知道你正在使用哪种编译器,我无法阅读它...