С++ для начинающих


Арифметические преобразования типов


Арифметические преобразования приводят оба операнда бинарного арифметического выражения к одному типу, который и будет типом результата выражения. Два общих правила таковы:

  • типы всегда приводятся к тому из типов, который способен обеспечить наибольший диапазон значений при наибольшей точности. Это помогает уменьшить потери точности при преобразовании;
  • любое арифметическое выражение, включающее в себя целые операнды типов, меньших чем int, перед вычислением всегда преобразует их в int.
  • Мы рассмотрим иерархию правил преобразований, начиная с наибольшего типа long double.

    Если один из операндов имеет тип long double, второй приводится к этому же типу в любом случае. Например, в следующем выражении символьная константа 'a' трансформируется в long double (значение 97 для представления ASCII) и затем прибавляется к литералу того же типа: 3.14159L + 'a'.

    Если в выражении нет операндов long double, но есть операнд double, все преобразуется к этому типу. Например:

    int    iva1;

    float fval;

    double dval;

    // fva1 и iva1 преобразуются к double перед сложением

    dval + fva1 + ival;

    В том случае, если нет операндов типа double и long double, но есть операнд float, тип остальных операндов меняется на float:

    char cvat;

    int iva1;



    float fva1;

    // iva1 и cval преобразуются к float перед сложением

    cvat + fva1 + iva1;

    Если у нас нет вещественных операндов , значит, все они представляют собой целые типы. Прежде чем определить тип результата, производится преобразование, называемое приведением к целому: все операнды с типом меньше, чем int, заменяются на int.

    При приведении к целому типы char, signed char, unsigned char и short int преобразуются в int. Тип unsigned short int трансформируется в int, если этот тип достаточен для представления всего диапазона значений unsigned short int (обычно это происходит в системах, отводящих полслова под short и целое слово под int), в противном случае unsigned short int заменяется на unsigned int.

    Тип wchar_t и перечисления приводятся к наименьшему целому типу, способному представить все их значения. Например, в перечислении


    enum status { bad, ok };

    значения элементов равны 0 и 1. Оба эти значения могут быть представлены типом char, значит char и станет типом внутреннего представления данного перечисления. Приведение к целому преобразует char в int.

    В следующем выражении

    char cval;

    bool found;

    enum mumble { ml, m2, m3 }      mval;

    unsigned long ulong;

    cval + ulong; ulong + found; mval + ulong;

    перед определением типа результата cval, found и mval преобразуются в int.

    После приведения к целому сравниваются получившиеся типы операндов. Если один из них имеет тип unsigned long, то остальные будут того же типа. В нашем примере все три объекта, прибавляемые к ulong, приводятся к типу unsigned long.

    Если в выражении нет объектов unsigned long, но есть объекты типа long, тип остальных операндов меняется на long. Например:

    char cval;

    long lval;

    // cval и 1024 преобразуются в long перед сложением

    cval + 1024 + lval;

    Из этого правила есть одно исключение: преобразование unsigned int в long происходит только в том случае, если тип long способен вместить весь диапазон значений unsigned int. (Обычно это не так в 32-битных системах, где и long, и int представляются одним машинным словом.) Если же тип long не способен представить весь диапазон unsigned int, оба операнда приводятся к unsigned long.

    В случае отсутствия операндов типов unsigned long и long, используется тип unsigned int. Если же нет операндов и этого типа, то к int.

    Может быть, данное объяснение преобразований типов несколько смутило вас. Запомните основную идею: арифметическое преобразование типов ставит своей целью сохранить точность при вычислении. Это достигается приведением типов всех операндов к типу, способному вместить любое значение любого из присутствующих в выражении операндов.


    Содержание раздела