C 什么';“的意思是什么;强制转换指定转换“?”;?

C 什么';“的意思是什么;强制转换指定转换“?”;?,c,language-lawyer,c99,typecasting-operator,C,Language Lawyer,C99,Typecasting Operator,在C 1999注释86中,对6.5.4.5(粗体) 如果表达式的值以比要求更高的精度或范围表示 根据类型转换命名的类型(6.3.1.8),则该类型转换指定转换,即使 表达式的类型与命名类型相同 b=(短)a+(短)b。这是一个例子 如果表达式的值以比要求更高的精度或范围表示 根据铸件命名的类型(6.3.1.8) 因为如果没有强制转换,a和b都被提升为int,这比强制转换命名的类型short的精度或范围更高(假设short为16位,int为32位)。 那么,在这种情况下,后一句话 然后,即使表达式

在C 1999注释86中,对6.5.4.5(粗体)

如果表达式的值以比要求更高的精度或范围表示 根据类型转换命名的类型(6.3.1.8),则该类型转换指定转换,即使 表达式的类型与命名类型相同

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

如果表达式的值以比要求更高的精度或范围表示 根据铸件命名的类型(6.3.1.8)

因为如果没有强制转换,
a
b
都被提升为
int
,这比强制转换命名的类型
short
的精度或范围更高(假设
short
为16位,
int
为32位)。

那么,在这种情况下,后一句话

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

我想知道这是如何影响
b=(短)a+(短)b


我的想法很简单。由于
(cast)
的优先级高于加法
+
,因此首先
a
b
(short)
进行cast,然后
+
的两个操作数通过通常的算术转换进行转换。但是“then the cast指定转换,即使表达式的类型与命名类型相同”这句话让我感到困惑。

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

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.27中。这些差异可能有一定的意义,但此处不讨论。)

这意味着,当您使用
double
计算表达式时,编译器可能会生成使用
长double
的代码。或者,当使用
float
计算表达式时,编译器可能会使用
double
long 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)

所以情况是这样的:浮点表达式可以使用额外的范围和精度来计算。当存在隐式转换时,例如将
浮点
乘以
双精度
(通常的算术转换将
浮点
转换为
双精度
),此额外的范围和精度可能会保持不变。但是,当您在源代码中进行强制转换时,必须执行“实际转换”,将具有额外精度的值转换为可在标称类型中表示的值。这就是强制转换指定转换的意思

尽管赋值中的转换是隐式的,但执行此转换也需要赋值,正如我们在上面引用的5.2.4.2.2 10中所述。注65至6.3.1.8 2中也提到了这一点:

强制转换和赋值操作符仍然需要删除额外的范围和精度


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

粗体部分将是类似于
(double)5.0的铸件,您将
double
5.0
转换为
double
@Someprogrammerdude,但
5.0
double
的类型相同,并且具有相同的精度和范围。您的意思是只固定了粗体部分吗?“…即使表达式的类型…”在
(double)5.0
的情况下,表达式是
5.0
。“…与命名类型相同”
(double)5.0
中的“命名类型”是
double
。因此,cast
(double)5.0
是从
double
double
的转换
signed char a = -2;
unsigned char b = 1;
b = (short)a + (short)b;