简体   繁体   English

带括号的子表达式的类型提升规则是什么?

[英]What is the type promotion rule for a parenthesized sub-expression?

Assume an integer expression comprised of multiple unsigned integral types uint16_t and uint32_t .假设一个整数表达式由多个无符号整数类型uint16_tuint32_t The expression contains a parenthesized sub-expression, within which all elements are of type uint16_t .该表达式包含一个带括号的子表达式,其中所有元素都是uint16_t类型。

Should the elements inside the parenthesized sub-expression be promoted to uint32_t prior to evaluating the sub-expression?在评估子表达式之前,括号内的子表达式中的元素是否应该被提升为uint32_t

For example:例如:

#include <stdint.h>
#include <stdio.h>

int main(void)
{
    uint16_t a16 = 0x2000;
    uint16_t b16 = 0x3000;
    uint32_t c32 = 0x00000001;
    uint32_t d32;

    // Should (a16 * b16) be evaluated to 0x06000000, or to 0x0000?
    // Should d32 be evaluated to 0x06000001, or to 0x00000001?
    d32 = c32 + (a16 * b16);

    printf("d32=0x%08x\n", d32);

    return 0;
}

Trying this in ideone online compiler suggests that a16 and b16 are promoted to uint32_t prior to the multiplication.ideone在线编译器中尝试此操作表明a16b16在乘法之前被提升为uint32_t Is this mandated by the C standard?这是 C 标准规定的吗? Why not evaluate to uint16_t while inside the parentheses?为什么不在括号内计算为uint16_t

All types narrower than int are promoted to an int prior to the multiplication.在乘法之前,所有比int窄的类型都被提升为int

So if you have a 32 bit 2's complement int then the result is effectively a product of two int32_t types.因此,如果您有一个 32 位 2 的补码int那么结果实际上是两个int32_t类型的乘积。

The parentheses in your expression have no effect on either this implicit type conversion, or the final result.表达式中的括号对这种隐式类型转换或最终结果都没有影响。

Anytime a type smaller than int is used an an expression it is first promoted to int or unsigned int regardless of the context of the expression.无论何时将小于int的类型用于表达式,无论表达式的上下文如何,它都会首先提升为intunsigned int

This is spelled out in section 6.3.1.1p2 of the C standard :这在C 标准的第 6.3.1.1p2 节中有详细说明:

The following may be used in an expression wherever an int or unsigned int may be used可以在可以使用intunsigned int的表达式中使用以下内容

  • An object or expression with an integer type (other than int or unsigned int ) whose integer conversion rank is less than or equal to the rank of int and unsigned int .具有整数类型(除了intunsigned int )的对象或表达式,其整数转换等级小于或等于intunsigned int的等级。
  • A bit-field of type _Bool , int , signed int ,or unsigned int . _Boolintsigned intunsigned int类型的位域。

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int ;如果int可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为int otherwise, it is converted to an unsigned int .否则,它被转换为unsigned int These are called the integer promotions.这些被称为整数提升。 All other types are unchanged by the integer promotions所有其他类型都不受整数促销的影响

So in your case, a16 and b16 will both be promoted to int before being applied to any operator, assuming that int is larger than uint16_t .因此,在您的情况下, a16b16在应用于任何运算符之前都将被提升为int ,假设int大于uint16_t

Note that that this is integer promotions , which is not the same as the usual arithmetic conversions .请注意,这是整数提升,与通常的算术转换不同 The latter dictates how two operands of different types are converted to a common type before applying the operator.后者规定了在应用运算符之前如何将不同类型的两个操作数转换为公共类型。

Assume an integer expression comprised of multiple unsigned integral types uint16_t and uint32_t.假设一个整数表达式由多个无符号整数类型 uint16_t 和 uint32_t 组成。 The expression contains a parenthesized sub-expression, within which all elements are of type uint16_t.该表达式包含一个带括号的子表达式,其中所有元素都是 uint16_t 类型。

Should the elements inside the parenthesized sub-expression be promoted to uint32_t prior to evaluating the sub-expression?在评估子表达式之前,括号内的子表达式中的元素是否应该被提升为 uint32_t?

No. There are two main possibilities:不,主要有两种可能性:

  1. uint16_t is the same type as unsigned int . uint16_tunsigned int类型相同。 In this case, no promotions are performed in evaluating operations with two uint16_t operands, and the result has type uint16_t .在这种情况下,在计算具有两个uint16_t操作数的操作时不会执行任何提升,并且结果的类型为uint16_t

  2. int is wider than uint16_t , and can therefore represent all the values representable by uint16_t . int比更宽uint16_t ,因此可以表示所有的值所能表述由uint16_t In this case, when both operands of a binary operator have type uint16_t , both are promoted to int (which is definitely not the same as uint32_t ), and the result of the operation has type int .在这种情况下,当一个二元运算符的两个操作数都具有uint16_t类型时,两者都被提升为int (这绝对与uint32_t ),并且运算结果的类型为int

In principle, C does not exclude a third possibility that in practice you will never see:原则上,C 不排除在实践中您永远不会看到的第三种可能性:

  1. uint16_t is not the same type as unsigned int , but is the same size. uint16_tunsigned int类型不同,但大小相同。 In this case you will either have promotion to unsigned int (which cannot be the same as uint32_t in this case) or no promotion.在这种情况下,您将升级为unsigned int (在这种情况下不能与uint32_t相同)或不升级。

Under no circumstance permitted to a conforming C implementation will the operands in question be promoted to uint32_t , nor will the operations with two uint16_t operands yield a uint32_t result.在符合 C 实现允许的任何情况下,相关操作数都不会提升为uint32_t ,具有两个uint16_t操作数的操作也不会产生uint32_t结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM