对于大于32,767的值,如何转换为“signed int”并返回“signed short”?

时间:2012-08-15 00:10:18

标签: c++ c variables types casting

代码:

typedef signed   short  SIGNED_SHORT;   //16 bit
typedef signed   int    SIGNED_INT;     //32 bit


SIGNED_SHORT x;

x = (SIGNED_SHORT)(SIGNED_INT) 45512; //or any value over 32,767

以下是我所知道的:

  

签名16位:
  签名:从-32,768到32,767
  无符号:从0到65,535

不要指望45512适合x,因为x被声明为16位有符号整数。

上面的双重演员如何以及做什么?

谢谢!

4 个答案:

答案 0 :(得分:5)

当你施放两次时,按顺序施放石膏。

int a = 45512;
int b = (int) a;
short x = (short) b;

由于45512在大多数(但不是全部!)平台上都不适合short,因此这些平台上的强制转换溢出。这将引发实现定义的信号或导致实现定义的值。

实际上,许多平台将结果定义为截断值,在这种情况下为-20024。但是,有些平台会发出信号,如果未被捕获,可能会终止你的程序。

引用:n1525§6.3.1.3

  

否则,新类型已签名且值无法在其中表示;无论是   结果是实现定义的或引发实现定义的信号。

答案 1 :(得分:5)

typedef signed   short  SIGNED_SHORT;   //16 bit
typedef signed   int    SIGNED_INT;     //32 bit

这些typedef并不是特别有用。 typedef只是为现有类型提供新名称。类型signed short已经有一个非常好的名字:“signed short”;称它为SIGNED_SHORT也不会给你买任何东西。 (如果它抽象出一些关于类型的信息,或者类型是否可能会改变,那将是有意义的 - 但使用名称SIGNED_SHORT作为signed short以外的类型将非常 令人困惑。)

另请注意,shortint都保证至少 16位宽,int至少与{{1}一样宽但是,不同的大小是可能的。例如,编译器可以同时生成shortshort 16位 - 或64位。但是我会假设编译器的大小与你说的一样。

此外,intsigned short是同一类型的名称,shortsigned int也是。

int

强制转换指定转换为指定类型。两个演员指定两个这样的转换。值SIGNED_SHORT x; x = (SIGNED_SHORT)(SIGNED_INT) 45512; //or any value over 32,767 将转换为45512,然后转换为signed int

常量signed short已经是45512类型(int的另一个名称),所以最里面的演员阵容是毫无意义的。 (请注意,如果signed int仅为16位,则int将为45512类型。)

当您将一个数值类型的值分配给另一个数字类型的对象时,该值会隐式转换为对象的类型,因此最外层的强制转换也是多余的。

所以上面的代码片段完全等同于:

long

鉴于系统中short x = 45512; int的范围,数学值short无法在类型45512中表示。语言规则声明这种转换的结果是实现定义的,这意味着由每个实现决定结果是什么,并且它必须记录该选择,但是不同的实现可以以不同的方式执行。 (实际上,这不是相当整个故事; 1999 ISO C标准增加了这种转换的许可,以提出实现定义的信号。我不知道有任何编译器这样做。)

这种转换最常见的语义是结果得到源值的低位。这将可能导致值short被分配给-20024。但是如果你想让你的程序最大程度地移植,你就不应该依赖它。

答案 2 :(得分:4)

双重铸造相当于:

short x = static_cast<short>(static_cast<int>(45512));

相当于:

short x = 45512;

可能会回滚,因此x等于-20024,但从技术上讲,如果short在您的平台上的最大值小于45512,则它是实现定义的行为。文字45512的类型为int

答案 3 :(得分:2)

您可以假设它进行了两次类型转换(尽管{C}标准IIRC中signed intint只分开了一次。

如果SIGNED_SHORT太小而无法处理45512,则结果是实现定义或引发实现定义的信号。 (在C ++中只有前者适用。)