Spec-Zone.ru › C

Оператор приведения типов

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

Синтаксис

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

где

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

Объяснение

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

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

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

Разрешается любое неявное преобразование как при присваивании.

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

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

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

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

Примечания

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

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

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

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

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

(с C99)

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

Пример

#include <stdio.h>
 
int main(void)
{
    // examining object representation is a legitimate use of cast
    double d = 3.14;
    printf("The double %.2f (%a) is: ", d, d);
    for (size_t n = 0; n < sizeof d; ++n)
        printf("0x%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: 0x1f 0x85 0xeb 0x51 0xb8 0x1e 0x09 0x40

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2023):
    • 6.5.4 Операторы приведения типов (стр. TBD)
  • Стандарт 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++ для явного преобразования типов

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/cast

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API