Namespaces
Variants

cast operator

From cppreference.net

Выполняет явное преобразование типа

Содержание

Синтаксис

( имя-типа ) выражение

где

type-name - либо тип void , либо любой скалярный тип
expression - любое выражение скалярного типа (если только type-name не является void , в этом случае может быть любым)

Объяснение

Если type-name имеет тип void , тогда expression вычисляется для побочных эффектов, а возвращаемое значение отбрасывается, аналогично случаю, когда expression используется самостоятельно в качестве выражения-оператора .

В противном случае, если type-name точно соответствует типу expression , ничего не делается (за исключением случая, когда expression имеет плавающий тип и представлен с большим диапазоном и точностью, чем указывает его тип – см. ниже).

В противном случае значение expression преобразуется в тип, указанный type-name , следующим образом:

Каждая неявная конверсия как при присваивании разрешена.

В дополнение к неявным преобразованиям, разрешены следующие преобразования:

  • Любое целое число может быть приведено к любому указателю. За исключением констант нулевого указателя, таких как NULL (которым не требуется приведение ), результат определяется реализацией, может быть некорректно выровнен, может не указывать на объект целевого типа и может быть trap representation .
  • Любой указатель может быть приведен к любому целочисленному типу. Результат определяется реализацией, даже для нулевых указателей (они не обязательно дают значение ноль). Если результат не может быть представлен в целевом типе, поведение не определено (беззнаковые целые не реализуют модульную арифметику при приведении из указателя).
  • Любой указатель на объект может быть приведен к любому другому указателю на объект. Если значение не имеет корректного выравнивания для целевого типа, поведение не определено. В противном случае, если значение преобразуется обратно в исходный тип, оно сравнивается как равное исходному значению. Если указатель на объект приводится к указателю на любой символьный тип, результат указывает на младший байт объекта и может быть инкрементирован до sizeof целевого типа (другими словами, может использоваться для изучения object representation или создания копии через memcpy или memmove ).
  • Любой указатель на функцию может быть приведен к указателю на любой другой тип функции. Если результирующий указатель преобразуется обратно в исходный тип, он сравнивается как равный исходному значению. Если преобразованный указатель используется для вызова функции, поведение не определено (если только типы функций не являются compatible ).
  • При приведении между указателями (как на объекты, так и на функции), если исходное значение является нулевым указателем своего типа, результат будет корректным нулевым указателем для целевого типа.

В любом случае (как при выполнении неявного преобразования, так и при приведении к тому же типу), если expression и type-name являются типами с плавающей точкой и expression представлено с большим диапазоном и точностью, чем указывает его тип (см. FLT_EVAL_METHOD ), диапазон и точность сокращаются для соответствия целевому типу.

Категория значения выражения приведения всегда является не-lvalue.

Примечания

Поскольку const , volatile , restrict и _Atomic квалификаторы действуют только на lvalues , приведение к cvr-квалифицированному или атомарному типу полностью эквивалентно приведению к соответствующему неквалифицированному типу.

Приведение к void иногда полезно для подавления предупреждений компилятора о неиспользуемых результатах.

Преобразования, не перечисленные здесь, не разрешены. В частности,

  • не существует преобразований между указателями и типами с плавающей точкой;
  • не существует преобразований между указателями на функции и указателями на объекты (включая void * ).

Если реализация предоставляет intptr_t и/или uintptr_t , то приведение указателя на объектный тип (включая cv void ) к этим типам всегда корректно определено. Однако это не гарантируется для указателей на функции.

(since C99)

Обратите внимание, что преобразования между указателями на функции и указателями на объекты принимаются как расширения многими компиляторами и ожидаются некоторыми вариантами использования POSIX-функции dlsym .

Пример

#include <stdio.h>
int main(void)
{
    // examining object representation is a legitimate use of cast
    const double d = 3.14;
    printf("The double %.2f (%a) is: ", d, d);
    for (size_t n = 0; n != sizeof d; ++n)
        printf("%02X ", ((unsigned char*)&d)[n]);
    // edge cases
    struct S { int x; } s;
    // (struct S)s; // error; not a scalar type, even though
                    // casting to the same type does nothing
    (void)s; // okay to cast any type to void
}

Вывод:

The double 3.14 (0x1.91eb851eb851fp+1) is: 1F 85 EB 51 B8 1E 09 40

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2024):
  • 6.5.5 Операторы приведения (стр. 83-84)
  • Стандарт C17 (ISO/IEC 9899:2018):
  • 6.5.4 Операторы приведения (стр: 65-66)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.5.4 Операторы приведения (стр: 91)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.5.4 Операторы приведения (стр: 81)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 3.3.4 Операторы приведения типов

Смотрите также

C++ documentation для явного преобразования типов