cast operator
Выполняет явное преобразование типа
Содержание |
Синтаксис
(
имя-типа
)
выражение
|
|||||||||
где
| 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
для
явного преобразования типов
|