Оператор приведения типов
Выполняет явное преобразование типов
Синтаксис
( имя_типа ) выражение |
где
| имя_типа | - | либо тип void или любой скалярный тип |
| выражение | - | любое выражение скалярного типа (если имя_типа не void, в этом случае может быть любое выражение) |
Объяснение
Если имя_типа это void, тогда выражение оценивается по своим побочным эффектам, и его возвращаемое значение отбрасывается, так же как и когда выражение используется само по себе, как выражение-оператор.
В противном случае, если имя_типа точно такой же тип, как у выражения, ничего не делается (кроме того, что если выражение имеет тип с плавающей точкой и представлено с большим диапазоном и точностью, чем указывает его тип — см. ниже).
В противном случае значение выражения преобразуется в тип, указанный имя_типа, следующим образом:
Разрешается любое неявное преобразование как при присваивании.
В дополнение к неявным преобразованиям разрешены следующие преобразования:
- Любое целое число может быть приведено к любому типу указателя. За исключением констант нулевого указателя, таких как
NULL(которое не требует приведения), результат зависит от реализации, может быть некорректно выровнен, может не указывать на объект указанного типа и может быть представлением ловушки. - Любой тип указателя может быть приведён к любому целочисленному типу. Результат зависит от реализации, даже для значений нулевого указателя (они не обязательно приводятся к значению ноль). Если результат не может быть представлен в целевом типе, поведение неопределённо (целые типы без знака не реализуют арифметику по модулю при приведении от указателя).
- Любой указатель на объект может быть приведён к любому другому указателю на объект. Если значение не выровнено для целевого типа, поведение неопределённо. В противном случае, если значение преобразуется обратно в исходный тип, оно сравнивается с исходным значением. Если указатель на объект приводится к указателю любого символьного типа, результат указывает на самый низкий байт объекта и может быть инкрементирован до sizeof целевого типа (другими словами, может использоваться для проверки представления объекта или для создания копии с помощью
memcpyилиmemmove). - Любой указатель на функцию может быть приведён к указателю на любой другой тип функции. Если полученный указатель преобразуется обратно в исходный тип, он сравнивается с исходным значением. Если преобразованный указатель используется для вызова функции, поведение неопределено (если типы функций совместимы).
- При приведении между указателями (объектами или функциями), если исходное значение — значение нулевого указателя своего типа, результат — правильное значение нулевого указателя для целевого типа.
В любом случае (как при выполнении неявного преобразования, так и при приведении к тому же типу), если выражение и имя_типа являются типами с плавающей точкой, и выражение представлено с большим диапазоном и точностью, чем указывает его тип (см. FLT_EVAL_METHOD), диапазон и точность отбрасываются для соответствия целевому типу.
Категория значения выражения приведения всегда не является lvalue.
Примечания
Поскольку const, volatile, restrict и _Atomic квалификаторы влияют только на lvalue, приведение к cvr-квалифицированному или атомарному типу точно эквивалентно приведению к соответствующему неквалифицированному типу.
Приведение к void иногда полезно для подавления предупреждений компилятора об игнорировании результатов.
Преобразования, не указанные здесь, не допускаются. В частности,
- нет преобразований между указателями и типами с плавающей точкой
- нет преобразований между указателями на функции и указателями на объекты (включая
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