从uint16_t到int32_t的铸造需要中间类型转换为int16_t

问题描述 投票:0回答:3

请参阅下面的代码。我感到困惑,为什么我需要先将变量var_u16强制转换为int16_t,然后再强制转换为int32_t才能正确解释为MyFunc()中的带符号int。

我会认为,由于var_u16具有最高有效位,因此,当简单地转换为int32_t时,编译器会理解这是一个负值。

相反,它仍然被解释为无符号值。为什么首先需要中间转换为int16_t

我正在使用gcc 8.3.0

#include <stdio.h>

void MyFunc(int32_t s32Var)
{
    printf("%d\n", s32Var);
}

int main()
{
    uint16_t var_u16 = 0x8000;
    MyFunc((int32_t)var_u16);          // prints 32768  
    MyFunc((int32_t)(int16_t)var_u16); // prints -32768 

    return 0;
}
c casting type-conversion unsigned signed
3个回答
1
投票

这里发生的是value正在从无符号的16位数字转换为有符号的32位数字。底层representation不相关。

由于任何可以存储在uint16_t中的值也可以存储在int32_t中,因此在转换为新类型时,该值保持不变。因此,值为[32768]的uint16_t变为值为[32768]的int32_t

由于中间值32768无法存储为该类型,因此中间转换为int16_t时会发生变化,因此该值将实现实现定义的转换,从而导致类型为int16_t的表达式具有值-32768。


1
投票

在第一种情况下,该值保持不变。发生这种情况是因为int32_t可以代表uint16_t的所有值。强制转换时,保留0x8000值,只是将其填充为零。

编译器会理解这是一个负值

这是不正确的。如果两种表示形式,0x8000是一个完全有效的正数。

int16_t不能保存uint16_t的所有值,并且0x8000是这些值之一。相反,通过模块化算术,32768变为-32768。强制转换为int32_t时,请对int16_t进行符号扩展,并保持-32768


0
投票

int32_t类型的对象可以存储uint16_t类型的值。

[当例如int16_t的有符号整数类型的对象转换为例如int32_t的较大的整数类型时,如果该对象的值为负,则其符号位将传播到较大的整数整数类型。

© www.soinside.com 2019 - 2024. All rights reserved.