gpt4 book ai didi

c - 减法中 16 位 int 机器和 32 位 int 机器之间的不同结果

转载 作者:行者123 更新时间:2023-12-02 06:29:20 24 4
gpt4 key购买 nike

当下面的代码针对像 MSP430 微 Controller 这样的 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。当它被分配给 s32 时,它是 32 位宽的有符号整数变量,转变是如何发生的?

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

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

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

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

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

enter image description here

最佳答案

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

这取决于 10 类型的表示(可以说是 int)。您的理解对于某些系统是正确的,我们将首先介绍这一点,但正如您稍后将在本回答中看到的那样,您遗漏了很大一部分内容。

Section 5.2.4, Environmental limits指定 int 类型的值范围从 -32767 到 32767;这个范围可以根据实现的判断进行扩展,但是 int必须能够代表这个范围。

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

Section 6.3.1.3, Signed and unsigned integers告诉我们来回转换。我无法更好地解释它,所以这是直接引用:

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.

这一切都支持您的理论,即 int 值 10 将转换为 uint16_t 当且仅当 int 是一个十六位类型。 然而,section 6.3.1.8, usual arithmetic conversion首先应用规则来决定发生上述三种转换中的哪一种,因为当 int 大于 16 位时,这些规则会改变您查看转换的方式:

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

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?

根据 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.

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


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 值并存储为该值。


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

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

关于c - 减法中 16 位 int 机器和 32 位 int 机器之间的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44081308/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com