“投射指定转换”是什么意思?

问题描述

在C 1999注释86中,对6.5.4 5(我的粗体)讲话

如果表达式的值以比要求的精度或范围更大的精度表示 按类型转换(6.3.1.8)命名的类型,则类型转换指定一次转化,即使 表达式的类型与命名类型相同。

signed char a = -2;
unsigned char b = 1;
b = (short)a + (short)b;

b = (short)a + (short)b;。这是一个例子

如果表达式的值以比要求的精度或范围更大的精度表示 通过演员(6.3.1.8)命名的类型,

因为如果没有强制转换,ab都将提升为int,其精度或范围要比short(命名类型)高按强制转换(假设short是16位而int是32位)。

然后,在这种情况下,后一句话

然后,即使表达式的类型与命名的类型相同,强制类型转换也将指定转换。

我想知道这如何影响b = (short)a + (short)b;

我的想法很简单。因为(cast)的优先级高于加法器+,所以首先ab(short)强制转换,然后+的两个操作数由通常的算术转换。但是句子“然后,即使表达式的类型与命名的类型相同,强制转换也指定了转换”。

解决方法

这是关于浮点类型的。整数类型不受影响。

b =(短)a +(短)b;。这是一个示例,例如“如果表达式的值比所需的精度或范围更大……”

否,该语句中的整数强制转换不是该示例。 C 2018 6.3.1.8 2(与C 1999相同)告诉您有关浮点类型的信息:

浮点操作数的值和浮点表达式的结果可以用比类型所需的更大的范围和精度来表示;类型不会因此改变。

这里发生的是,根据C 2018 5.2.4.2.2 10:C标准允许以比其标称类型更大的范围和精度来计算浮点表达式:

除了赋值和强制类型转换(这会删除所有额外的范围和精度)之外,具有浮动操作数的运算符产生的值以及需要进行常规算术转换的值和具有浮动常数的值都将被评估为其范围和精度可能更大的格式比类型所要求的...

(在C 1999中,相似的文本出现在5.4.2.2.2 7.上,这些差异可能具有一定的意义,但此处不再讨论。)

这意味着,当您使用double计算表达式时,编译器可能会生成例如使用long double的代码。或者,当您使用float计算表达式时,编译器可能会使用doublelong double。例如,这使在具有用于加载和存储单精度(float)或双精度(double)浮点数据的指令的处理器上实现C变得更容易,但是该处理器具有指令仅用于计算双精度浮点,而不用于单精度。

您从C 1999中引用的注释86在C 2018中被提升为标准文本,如6.5.4 6:

如果表达式的值所表示的范围或精度大于强制转换所命名的类型(6.3.1.8)所要求的范围,则强制转换会指定一个转换,即使表达式的类型与命名类型相同输入并删除所有多余的范围和精度。

这告诉你的是,演员必须“去除”额外的射程和精度。 (这是不幸的措辞;最好用适用的舍入规则将值四舍五入为可在命名类型中表示的值,通常是四舍五入关系。)

在C 2018 6.3.1.5 1中(在C 1999中不存在),关于浮点类型之间的转换,我们看到:

…某些隐式转换的结果可能比新类型所要求的范围和精度更高(请参见6.3.1.8和6.8.6.4)。

情况是这样的:浮点表达式可以使用额外的范围和精度来计算。如果存在隐式转换,例如将float乘以double(通常的算术转换将float转换为double),则此额外的范围和精度可能会保持。但是,当您在源代码中进行强制转换时,必须执行“实际转换”,以超高精度将值转换为名义类型可表示的值。这就是说演员阵容指定了转化。

尽管赋值中的转换是隐式的,但如上面引用的5.2.4.2.2 10中所述,执行此转换也需要赋值。 6.3.1.8 2的注释65中也指出了这一点:

仍然需要强制转换和赋值运算符来删除额外的范围和精度。

可能需要注意的是,return语句执行隐式转换,但不需要删除多余的范围或精度。