不同的结果在16位的int机器(MSP430)和32位的int机器(ARM CORTEX)中进行减法运算 [英] Different results in 16 bit int machine(MSP430) and 32 bit int machine(ARM CORTEX) in a subtraction

查看:338
本文介绍了不同的结果在16位的int机器(MSP430)和32位的int机器(ARM CORTEX)中进行减法运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  #include< stdint.h> 

uint16_t u16c;
int32_t s32;

int main()
{

u16c = 100U;
s32 = 10 - u16c;
}

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



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

二进制表示为90是 00000000 01011010
当这个被赋值给$ 32 code> s32 这是32位宽的有符号整数变量,
转换如何发生?



为了 s32 等于65446,90需要2的补码。
这将是 00000000 10100110



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



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



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



如IAR Workbench(右下角)所示,添加了 s32 的六进制数据表示)。
显示 s32 成为 0x0000FFA6
因此,对于MSP430,机器实现从无符号16位转换为32位,只需预先添加16位。



解决方案


我的理解是 u16c 将隐式类型提升到 unsigned int


这取决于 10 int 的类型的表示形式)。您的理解对于某些系统来说是正确的,我们将首先介绍一下,但正如您将在后面的答案中看到的那样,您将失去图片的很大一部分。



第5.2.4节,环境限制指定类型为 int 的值的范围为-32767到32767;该范围可以由实现自行扩展,但 int 必须可以表示此范围。



uint16_t ,但是,如果它存在(它不是需要)有一个范围从0到65535.实现不能扩展;这是一个要求,准确地 [0..65535] (因此这种类型不需要存在的原因)。 p>

第6.3节.1.3,签名和无符号整数告诉我们来回转换。我不能更好地改写,所以这里是直接引用:


1当整数类型的值转换为另一个整数类型时比_Bool,如果值可以由新的类型表示,它是不变的。



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



3否则,新类型被签名,值不能代表它;结果是实现定义的或实现定义的信号被提出。


这一切都支持你的理论, int 如果且仅当 int 值10将被转换为 uint16_t / code>是一个16位类型。 但是,第6.3.1.8节,通常的算术应该首先应用 规则,以确定上述三种转换中的哪一种,因为这些规则会更改您在 int 大于16位


如果两个操作数的类型相同,否则,如果两个操作数都具有符号整数类型,或者两者都具有无符号整数类型,那么转换次数较小的类型的操作数将被转换为



对于具有更大等级的操作数的类型。



否则,如果具有无符号整数类型的操作数具有等于或大于其他操作数类型的等级,则带有符号整数类型的操作数将转换为具有无符号整数类型的操作数类型。



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



否则,两个操作数都将转换为与具有带符号整数类型的操作数类型相对应的无符号整数类型。







所以,从这里可以看出,表达式的类型 10-u16c 可能因系统而异。在 int 是十六位的系统上,该表达式将是一个 uint16_t


数学上10-u16c等于-90。但是可以将负数表示为unsigned int。当-90被提升为unsigned int时,是否意味着一个数字的符号被忽略?


根据附件H.2.2


C的无符号整数类型在LIA-1意义上是modulo,因为溢出或超出界限的结果将静默地包裹。


换句话说,如果 10 转换为 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 。这样做可以解决这个问题吗?


类型转换没有为此讨论添加有用的信息。也许您使用的是非兼容(buggy)编译器。我怀疑手册可能会对此有所了解,但由于我不知道您使用哪个编译器,我无法读取...


When the code below is run against 16-bit integer machine like MSP430 micro controller, s32 yields 65446.

#include <stdint.h>

uint16_t   u16c;
int32_t    s32;

int main()
{

    u16c = 100U;
    s32  = 10 - u16c;
}

My understanding is that 10-u16c gets implicit type promotion to unsigned int. Mathematically 10-u16c equals to -90. But how is it possible to represent a negative number as an unsigned int. When -90 gets promoted to unsigned int, does it mean that the sign of a number is ignored?

Lets suppose, the sign of a number is ignored.
The binary representation of 90 is 00000000 01011010. When this gets assigned to s32 which is 32 bit wide signed integer variable, how does the transformation takes place?

In order for s32 equal to 65446, 90 has to take 2's complement. That would be 00000000 10100110.

I am not confident in understand the process of s32 becoming 65446.

In 32bit wide integer machine like ARM, s32 is -90, which is correct.

To fix this situation in 16bit integer machine, there needs a typecast of (int16_t) for u16c. How does this remedy this problem?

Added hexa data representation of s32 as shown from IAR Workbench (Lower right corner). It is shown that s32 becomes 0x0000FFA6. So for MSP430, the machine implementation of converting from unsigned 16 bit to signed 32 bit, it simply prepends 16 0's bits.

解决方案

My understanding is that 10-u16c gets implicit type promotion to unsigned int.

This depends upon the representation of the type of 10 (int, as it were). Your understanding is correct for some systems, and we'll cover that first, but as you'll see later on in this answer, you're missing a big part of the picture.

Section 5.2.4, Environmental limits specifies that values of type int can range from -32767 to 32767; this range may be extended at the discretion of implementations, but int values must be able to represent this range.

uint16_t, however, if it exists (it's not required to) has a range from 0 to 65535. Implementations can't extend that; it's a requirement that the range be precisely [0..65535] (hence the reason this type isn't required to exist).

Section 6.3.1.3, Signed and unsigned integers tells us about the conversions to and fro. I couldn't paraphrase it better, so here's a direct quote:

1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

2 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)

3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

This all supports your theory that the int value 10 would get converted to a uint16_t if and only if int is a sixteen bit type. However, section 6.3.1.8, usual arithmetic conversion rules should be applied first to decide which of the three above conversions takes place, as these rules change the way you'll look at the conversion when int is greater than sixteen bits:

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.


So, as you can see from this, the type of the expression 10-u16c might vary from system to system. On systems where int is sixteen bits, that expression will be a uint16_t.

Mathematically 10-u16c equals to -90. But how is it possible to represent a negative number as an unsigned int. When -90 gets promoted to unsigned int, does it mean that the sign of a number is ignored?

According to Annex H.2.2:

C's unsigned integer types are ''modulo'' in the LIA-1 sense in that overflows or out-of-bounds results silently wrap.

In other words, if 10 gets converted to a uint16_t and the subtraction is performed, the result will be a large number, in this case you can see that number by explicitly converting both operands (i.e. casting them) to a uint16_t. You could see a similar effect by using unsigned integer constants such as -90U. This is largely supported by rule #2 from the quote from 6.3.1.3 earlier.


When this gets assigned to s32 which is 32 bit wide signed integer variable, how does the transformation takes place?

The expression 10-u16c is converted according to rule #1 in 6.3.1.3 (quoted above) to an int32_t value and stored as that value.


To fix this situation in 16bit integer machine, there needs a typecast of (int16_t) for u16c. How does this remedy this problem?

The typecast adds no useful information to this discussion. Perhaps you're using a non-compliant (buggy) compiler. I suspect the manual might shed some light on this, but since I don't know which compiler you're using I can't read it...

这篇关于不同的结果在16位的int机器(MSP430)和32位的int机器(ARM CORTEX)中进行减法运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆