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

查看:41
本文介绍了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.但是如何将负数表示为无符号整数?

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 工作台(右下角)所示.结果表明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 并执行减法,结果将是一个数,在在这种情况下,您可以通过将两个操作数(即转换它们)显式转换为 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.

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

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天全站免登陆