16位int机器和32位int机器在减法中的不同结果 [英] Different results between a 16-bit int machine and a 32-bit int machine in a subtraction

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

问题描述

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

When the code below is run against a 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;
}

我的理解是 10 - u16c 将隐式类型提升为 unsigned int.数学上 10 - u16c 等于 -90.但是如何将负数表示为 unsigned int 呢?

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?

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

When -90 gets promoted to unsigned int, does it mean that the sign of a number is ignored?

假设,一个数字的符号被忽略了.
90的二进制表示是00000000 01011010.当它被分配给 s32 时,它是 32 位宽的有符号整数变量,转变是如何发生的?

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 take place?

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

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

我对s32变成65446的过程没有信心.

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

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

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

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

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

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

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.

推荐答案

我的理解是 10-u16c 得到隐式类型提升到 unsigned int.

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

这取决于 10 类型的表示(实际上是 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.

第 5.2.4 节,环境限制 指定int 类型的值的范围可以从 -32767 到 32767;这个范围可以根据实现的判断进行扩展,但是 int必须 能够代表这个范围.

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,然而,如果存在(它不是必需的)的范围是 0 到 65535.实现不能扩展那;要求范围精确 [0..65535](因此不需要此类型存在的原因).

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

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

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 当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的类型表示,则保持不变.

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 否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上反复加减一,直到该值在新类型的范围内.60)

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 否则,新类型是有符号的,值不能在其中表示;结果要么是实现定义的,要么引发实现定义的信号.

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.

这一切都支持你的理论,即 int 值 10 将被转换为 uint16_t 当且仅当 int 是十六位类型.但是,第 6.3.1.8 节,通常的算术转换 规则应首先 应用以决定发生上述三个转换中的哪一个,因为这些规则会改变您在 int 时查看转换的方式 大于十六位:

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.


因此,从这里可以看出,表达式 10-u16c 的类型可能因系统而异.在 int 为 16 位的系统上,该表达式将为 uint16_t.


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.

数学上 10-u16c 等于 -90.但是如何将负数表示为无符号整数.当 -90 提升为 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?

根据附件H.2.2:

C 的无符号整数类型是 LIA-1 意义上的模",因为溢出或越界结果会静默包装.

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

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

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.

当它被分配给 32 位宽的有符号整数变量 s32 时,如何进行转换?

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

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

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.

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

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机器和32位int机器在减法中的不同结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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