op *_* ol 5 c c99 language-lawyer typecasting-operator
在 C 1999 注释 86 中,对 6.5.4 5(我的粗体)说话
如果表达式的值表示的精度或范围比强制转换命名的类型(6.3.1.8)所要求的精度或范围大,则即使表达式的类型与命名类型相同,该强制转换也会指定转换。
signed char a = -2;
unsigned char b = 1;
b = (short)a + (short)b;
Run Code Online (Sandbox Code Playgroud)
b = (short)a + (short)b;. 这是一个例子
如果表达式的值表示的精度或范围比由强制转换 (6.3.1.8) 命名的类型所需的精度或范围更大,
因为如果没有强制转换,a并且b两者都被提升为int,这比short强制转换命名的类型(假设short是 16 位和int32 位)具有更高的精度或范围。
那么,在这种情况下,后一句
然后即使表达式的类型与命名类型相同,转换也会指定转换。
我想知道这会如何影响b = (short)a + (short)b;。
我的想法很简单。因为(cast)具有比加法更高的优先级+,首先a和b被强制转换(short),然后两个操作数+被转换为通常的算术转换。但是这句话“即使表达式的类型与命名类型相同,转换也指定了转换”让我感到困惑。
这是关于浮点类型的。整数类型不受影响。
\n\n\nb =(短)a +(短)b;。这是 \xe2\x80\x9c 的示例如果表达式的值以比所需更高的精度或范围表示\xe2\x80\xa6\xe2\x80\x9d
\n
不,该语句中的整数转换不是这样的示例。C 2018 6.3.1.8 2(与 C 1999 相同)告诉您它是关于浮点类型的:
\n\n\n浮点操作数的值和浮点表达式的结果可以用比类型所需的范围和精度更大的范围和精度来表示;类型不会因此改变。
\n
这里发生的情况是,根据 C 2018 5.2.4.2.2 10,C 标准允许以比其标称类型更大的范围和精度来计算浮点表达式:
\n\n\n除了赋值和转换(删除所有额外的范围和精度)之外,具有浮点操作数的运算符生成的值以及经过通常算术转换和浮点常量的值将被评估为其范围和精度可能大于所要求的格式类型\xe2\x80\xa6
\n
(在 C 1999 中,类似的文本出现在 5.4.2.2.2 7 中。这些差异可能有一定的意义,但这里不予讨论。)
\n这意味着,当您使用 计算表达式时double,编译器可能会生成使用 的代码long double。或者,当您使用 计算表达式时float,编译器可能会使用double或long double。例如,这使得在具有加载和存储单精度 ( float) 或双精度 ( double) 浮点数据指令但仅具有计算双精度浮点数据的指令的处理器上实现 C 变得更容易,不适用于单精度。
您在 C 1999 中引用的注释 86 已在 C 2018 中提升为规范性文本,如 6.5.4 6:
\n\n\n如果表达式值的表示范围或精度大于强制转换命名的类型 (6.3.1.8) 所需的范围或精度,则强制转换指定转换,即使表达式的类型与命名类型相同并删除任何额外的范围和精度。
\n
这告诉您的是,强制转换必须 \xe2\x80\x9cremove\xe2\x80\x9d 额外的范围和精度。(这是不幸的措辞;最好说该值使用任何适用的舍入规则舍入到命名类型中可表示的值,通常舍入到最接近的偶数。)
\n在 C 2018 6.3.1.5 1(C 1999 中不存在)中,关于浮点类型之间的转换,我们看到:
\n\n\n\xe2\x80\xa6 某些隐式转换的结果可能会以比新类型所需的范围和精度更大的范围和精度表示(参见 6.3.1.8 和 6.8.6.4)。
\n
所以情况是这样的:浮点表达式可以使用额外的范围和精度来计算。当存在隐式转换时,例如将 a 乘以floata double(通常的算术转换将 a 转换float为double)时,可能会保留此额外的范围和精度。但是,当您在源代码中进行强制转换时,必须执行 \xe2\x80\x9cactual conversion\xe2\x80\x9d,将具有额外精度的值转换为可在标称类型中表示的值。这就是强制转换指定转换的含义。
尽管赋值中的转换是隐式的,但执行此转换也需要赋值,如上面引用的 5.2.4.2.2 10 中所述。注 65 至 6.3.1.8 2 中也指出了这一点:
\n\n\n仍然需要强制转换和赋值运算符来删除额外的范围和精度。
\n
可能值得注意的是,return语句执行隐式转换,但不需要删除额外的范围或精度。
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |