C在short和int之间进行强制转换的规则是什么?

Jun*_*Jun 5 c

当使用C在short和int之间进行转换时,我很困惑.我假设short是16位而int是32位.我测试了下面的代码:

unsigned short a = 0xFFFF;
signed short b = 0xFFFF;

unsigned int u16tou32 = a;
unsigned int s16tou32 = b;
signed int u16tos32 = a;
signed int s16tos32 = b;

printf("%u %u %d %d\n", u16tou32, s16tou32, u16tou32, s16tou32);
Run Code Online (Sandbox Code Playgroud)

我得到的是:

  • u16tou32:65535
  • s16tou32:4294967295
  • u16tos32:65535
  • s16tos32:-1

我感到困惑的是s16到u32之间的转换,以及u16到s32之间的转换.似乎s16到u32正在进行"符号扩展",而u16到s32则没有.这背后的规则究竟是什么?这也是依赖于实现的吗?在C中进行这种类型的转换是否安全,或者我应该自己使用位操作来避免意外结果?

Who*_*aig 6

无论何时整数类型被转换为不同的整数类型,它都属于标准中的分类,称为整数提升,并且所有这些都被定义(其中一个是实现,但我们将到达最后一个;扰流器在上面的一般评论中提到).

关于价值鉴定的一般概述:

C99 6.3.1.1-p2

如果int可以表示原始类型的所有值(由宽度限制,对于位字段),则该值将转换为int; 否则,它将转换为unsigned int.这些被称为整数促销.整数促销不会更改所有其他类型.

也就是说,让我们来看看你的转换.的signed-short到unsigned int由下面的覆盖,因为值被转换落在外unsigned int域:

C99 6.3.1.3-p2

否则,如果新类型是无符号的,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.

这基本上意味着"添加UINT_MAX + 1".在你的机器上,UINT_MAX是4294967295,因此,这就变成了

-1 + 4294967295 + 1 = 4294967295
Run Code Online (Sandbox Code Playgroud)

关于您unsigned short的signed int转换,这是由常规价值优化促销所涵盖.特别:

C99 6.3.1.3-p1

当具有整数类型的值转换为除_Bool之外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变.

换句话说,因为你的价值unsigned short落在可以考虑的领域之内signed int,所以没有什么特别的东西可以做,而且只是保存了价值.

最后,如上面的一般评论所述,你的声明会发生一些特殊的事情 b

signed short b = 0xFFFF;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,0xFFFF是有符号整数.十进制值为65535.但是,该值无法通过signed short另一个转换发生,也许您不知道:

C99 6.3.1.3-p3

否则,新类型将被签名,并且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号.

换句话说,您的实现选择将其存储为(-1),但您不能依赖于不同的实现.