C++ 铸造是如何进行的;署名int";然后回到“我的朋友”;署名“short”;是否为大于32767的值工作?

C++ 铸造是如何进行的;署名int";然后回到“我的朋友”;署名“short”;是否为大于32767的值工作?,c++,c,variables,types,casting,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位: 签名:发件人−32768到32767 未签名:从0到65535 不要期望45512适合x,

代码:

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位:
签名:发件人−32768到32767
未签名:从0到65535

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

上面的双重铸造是如何进行的,又是如何进行的?


谢谢大家!

您可以假设它执行两种类型转换(尽管在C标准IIRC中,
signed int
int
仅分隔一次)


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

双注相当于:

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

这可能会使
x
等于
-20024
,但从技术上讲,如果平台上的short的最大值小于45512,则这是实现定义的行为。文本
45512
的类型为
int

当您进行两次强制转换时,将按顺序应用强制转换

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

x = (SIGNED_SHORT)(SIGNED_INT) 45512; //or any value over 32,767
由于45512不适合大多数(但不是所有!)平台上的
short
,因此这些平台上的强制转换溢出。这将引发一个实现定义的信号或产生一个实现定义的值

实际上,许多平台将结果定义为截断值,在本例中为
-20024
。然而,有些平台会发出信号,如果未触发,可能会终止您的程序

引文:n1525§6.3.1.3

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

这些
typedef
s不是特别有用。typedef只不过是为现有类型提供一个新名称。类型
已签名的short
已经有了一个非常好的名称:“
已签名的short
”;把它叫做“签名的”
SIGNED\u SHORT
也不会给你带来任何好处。(如果它提取了一些关于该类型的信息,或者该类型可能会更改,那么这是有意义的——但是将名称
SIGNED_SHORT
用于
SIGNED SHORT
以外的类型将非常混乱。)

还请注意,
short
int
都保证至少16位宽,
int
至少与
short
一样宽,但大小可能不同。例如,编译器可以将
short
int
都设置为16位,或者64位。但我假设编译器的大小与您所说的相同

此外,
signed short
short
signed int
是同一类型的名称

SIGNED_SHORT x;

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

常量
45512
的类型已经是
int
(有符号int的另一个名称),因此最里面的强制转换是毫无意义的。(请注意,如果
int
仅为16位,则
45512
的类型将为
long

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

因此,上述代码片段完全等效于:

short x = static_cast<short>(static_cast<int>(45512));
short x = 45512;
short x = 45512;
鉴于系统上的
int
short
范围,数学值
45512
不能用类型
short
表示。语言规则规定这种转换的结果是由实现定义的,这意味着由每个实现来确定结果是什么,并且它必须记录这种选择,但是不同的实现可以做得不同。(事实上,这还不是全部;1999年的ISO C标准增加了对这种转换的许可,以产生一个实现定义的信号。我不知道有哪种编译器能做到这一点。)


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

typo!!对不起,我被问题缠住了,45512但即使它不合适,我也会[天真地]期待同样的结果(即使结果是通过UB)。我当然希望在定义行为时使用这些语义(例如Java或C#)。在大多数情况下,如果整数不能容纳更大的数字,它将溢出。@Aesthete:我的错误,拼写错误,我的意思是任何超过32767Short的值都不保证为16位。你应该使用int16_t@matzahboy你错了。但是,
int
不能保证是32位。@matzahboy:在这个系统上是的。Short保证至少是16位。它不能保证精确到16位。这不是未定义的行为。@eq:你错了。答案是正确的。等等,应该有“在那些平台上”的资格,所以你是对的。很抱歉编辑:添加了重要的“在某些平台上”限定(黄鼠狼片段)。理解相同的源代码在某些平台上有UB,但在大多数平台上定义良好,这一点很重要。这一切都取决于所涉及的范围。@Cheersandhth.-Alf:这不是“一些”平台,而是“那些”平台——45512在短时间内不适合的平台。@Cheersandhth.-Alf,但在这个转换中似乎没有浮点类型。它不是UB。。。检查标准。问题标记为和<代码> STATICORCAST 是C++特有的。