Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/48: Рейтинг темы: голосов - 48, средняя оценка - 4.69
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001

Как работает reinterpret_cast?

07.11.2014, 07:04. Показов 10382. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
не пойму как работает reinterpret_cast? вот если мне надо например данные привести в бинар для сохранения в файл, я пишу:
C++
1
2
int value = 123;
char* buff = reinterpret_cast<char*>(value); //можно конечно и const, но и так проглатывает тоже
так вот после этого если сделать обратно преобразование то из buff получится тоже число, я чего не могу понять reinterpret_cast что сам выделяет память чтоли??? он работает с динамической памятью или только со статической? просто если с динамической то это же очень не безопасно, память могут не освободить... ведь фактического выделения не видно в коде... сам по себе указатель на массив символов buff не может хранить ничего... ему надо выделять память...
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.11.2014, 07:04
Ответы с готовыми решениями:

Приведение типов: как работает reinterpret_cast<>() ?
Хочу разобраться до конца с приведением типов а именно интересует reinterpret_cast&lt;&gt;(), хотя бы в общих чертах логика этой функции, на...

reinterpret_cast
Подскажите плиз, чем отличается функция reinterpret_cast от static_cast? небольшой пример: const int MAX = 100; // размер буфера ...

Reinterpret_cast
Не могу понять к чему тут этот каст и каким образом он влияет на результат. char zxc = ((*(reinterpret_cast&lt;const...

20
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
07.11.2014, 07:15
Что за обратное преобразование?
1
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 07:17  [ТС]
Цитата Сообщение от nmcf Посмотреть сообщение
Что за обратное преобразование?
ну соответственно:
C++
1
value = reinterpret_cast<int>(buff);
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 07:18
Цитата Сообщение от Dark Byte Посмотреть сообщение
данные привести в бинар для сохранения в файл
Что-то непонятное написано. Чтобы сохранить данные в бинарном формате в файл приведение к типу 'char *', если оно уж вам понадобилось, делается обычно так

C++
1
2
int value = 123;
char* buff = reinterpret_cast<char*>(&value);
после чего 'buff' указывает на начало объекта 'value' и можно сохранять бинарный буфер с адреса 'buff' и размером в 'sizeof(int)'. Тем самым в бинарном виде будет сохранено значение 'value'. (На самом деле правильно для таких целей использовать 'unsigned char *')

А то, что у вас написано

C++
1
2
int value = 123;
char* buff = reinterpret_cast<char*>(value);
это просто преобразование целого значения 123 из переменной 'value' к указателю на адрес 123. Язык не гарантирует результатов такого преобразования, но в типичной реализации получится именно это: указатель 'buff' будет указывать на адрес 123. Что там лежит по адресу 123 - никто не знает. Скорее всего ничего не лежит.

Обратное преобразование

C++
1
value = reinterpret_cast<int>(buff);
просто преобразует адрес 123 обратно к целочисленному значению 123.

Никакой дополнительной памяти ни для одного из этих преобразований не нужно, ни статической, ни динамической. Никакого выделения памяти тут нет. Откуда вы взяли эту идею про дополнительную память мне не ясно.
4
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 07:25  [ТС]
TheCalligrapher, ваш вариант абсолютно не рабочий, мой работает отлично, какие проблемы? вы бы хоть протестили прежде чем утверждать

Добавлено через 3 минуты
но во всяком случае я теперь понял, значит буффером используется память статически выделенная для статической переменной value, соответственно работы с динамической памятью нет и ничего освобождать не надо так?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 07:26
Цитата Сообщение от Dark Byte Посмотреть сообщение
ваш вариант абсолютно не рабочий,
Что за ерунду вы несете? Что значит "не рабочий"? Не рабочий для каких целей?

Показываю еще раз:

C++
1
2
3
4
5
ofstream of("test", ios_base::out | ios_base::binary);
 
int value = 123;
char* buff = reinterpret_cast<char*>(&value);
of.write(buff, sizeof(int));
Этот код записывает в файл содержимое переменной 'value' в бинарном виде, т.е. значение 123. Именно так это делается.

Где вы тут увидели что-то "нерабочее"?
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 07:28  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
value = reinterpret_cast<int>(buff);
я имел ввиду что обратное преобразование не проходит... в value записывается какой то бред...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 07:34
Цитата Сообщение от Dark Byte Посмотреть сообщение
я имел ввиду что обратное преобразование не проходит... в value записывается какой то бред...
Я не знаю, что вы там за "обратное преобразование" пробовали...

В данном случае прямое преобразование - то преобразование значения '&value' типа 'int *' в тип 'char *'. Соответственно обратное преобразование в этом случае - это преобразование типа 'char *' в тип 'int *'

C++
1
int *pvalue = reinterpret_cast<int *>(buff);
В переменной 'pvalue' получится адрес переменной 'value' (т.е. '&value'). Все как и должно быть. Никакого бреда.
1
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 07:39  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В данном случае прямое преобразование - то преобразование значения '&value' типа 'int *' в тип 'char *'. Соответственно обратное преобразование в этом случае - это преобразование типа 'char *' в тип 'int *
интересный номер... а к int я так понимаю нельзя? для этого типа как раз нужна будет лишняя память...

Добавлено через 2 минуты
а вот как мне соединить несколько таких бинарных переменных в одну? мне надо сделать сериализацию данных класса, в задании сказано что "– Serialize – функция сериализация данных. Функция должна сохранять все свои данные в буфер, указанный в параметрах функции.", т.е. я переделываю все переменные класса в эдакие бинарные буферы, и потом мне надо вернуть это все в одной переменной... как мне их объединить?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 07:42
Цитата Сообщение от Dark Byte Посмотреть сообщение
а к int я так понимаю нельзя?
Как это "нельзя"? Конечно можно!

Если сделать так

C++
1
2
3
int value = 123;
char* buff = reinterpret_cast<char*>(&value);
int another_value = reinterpret_cast<int>(buffer);
то в переменную 'another_value' фактически ляжет числовое значение адреса переменной 'value'. Никакой лишней памяти тут не будет выделяться.

Тут, разумеется, есть тонкости. Во-первых, если адрес на данной платформе не помещается в 'int', то значение в 'another_value' получится "обрезанным". Во-вторых, какой-то бит адреса попадет в знаковый бит 'int', и если этот бит равен 1, то результат в 'another_value' получится отрицательным.

Для подобных манипуляций не рекомендуется использовать знаковые типы.

В заголовочном файле <cinttypes> есть специальный тип 'uintptr_t', который как раз и предназначен для подобных манипуляций. Т.е.

C++
1
uintptr_t another_value = reinterpret_cast<uintptr_t>(buffer);
практически всегда аккуратно положит значение адреса в переменную 'another_value'.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 07:58  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
то в переменную 'another_value' фактически ляжет числовое значение адреса переменной 'value'.
так вот что за фигня у меня туда записывалась)))) ну это не то что мне нужно, ладно int* так int*...

Добавлено через 4 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В заголовочном файле <cinttypes> есть специальный тип 'uintptr_t', который как раз и предназначен для подобных манипуляций.
полистал темки внизу однако...
Цитата Сообщение от Убежденный Посмотреть сообщение
Например, в C я легко могу привести указатель к какому-нибудь char-у или наоборот, и
компилятор даже не пикнет. Со static_cast такой номер не пройдет, и даже
reinterpret_cast не позволит это сделать, если размер output-типа слишком мал.
Добавлено через 8 минут
C++
1
2
3
4
5
template<typename T>
inline const char* bin(const T& value)
{
    return reinterpret_cast<const char*>(&value);
}
Добавлено через 1 минуту
а что по сериализации подскажете?
Цитата Сообщение от Dark Byte Посмотреть сообщение
а вот как мне соединить несколько таких бинарных переменных в одну? мне надо сделать сериализацию данных класса, в задании сказано что "– Serialize – функция сериализация данных. Функция должна сохранять все свои данные в буфер, указанный в параметрах функции.", т.е. я переделываю все переменные класса в эдакие бинарные буферы, и потом мне надо вернуть это все в одной переменной... как мне их объединить?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 08:04
Цитата Сообщение от Dark Byte Посмотреть сообщение
Цитата Сообщение от Убежденный
Например, в C я легко могу привести указатель к какому-нибудь char-у или наоборот, и
компилятор даже не пикнет. Со static_cast такой номер не пройдет, и даже
reinterpret_cast не позволит это сделать, если размер output-типа слишком мал.
В процитированном сообщении от Убежденный большое количество дезинформации.

Во-первых, даже язык С запрещает неявное преобразование указателей в целые и обратно. Такое преобразование в языке С всегда требует явного приведения типа, т.е. каста.

C
1
2
3
4
5
int i = 10;
char *p;
 
p = i; /* <- Ошибка. Запрещается в языке С!!! */
p = (char *) i; /* <- Требуется явное приведение типа */
Однако по чисто историческим причинам (для облегчения поддержки С-кода времен динозавров) многие компиляторы С разрешают выполнять такое преобразование неявно, без каста. Тем не менее компилятор обязан выдавать хотя бы предупреждение на код, который требует такого неявного преобразования. Компиляторы, который "даже не пикают" в такой ситуации не являются компиляторами языка С.

Во-вторых, в языке С++ при помощи 'reinterpret_cast' можно выполнять преобразование указателей к целочисленным типам даже если целевой тип слишком мал. Утверждение вышепроцитированного автора о том, что 'reinterpret_cast' не позволит этого сделать - ложно. 'reinterpret_cast' просто породит какой-то "урезанный" результат.
1
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 08:09  [ТС]
кстати почему?
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
На самом деле правильно для таких целей использовать 'unsigned char *'
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 08:23
Цитата Сообщение от Dark Byte Посмотреть сообщение
кстати почему?
Это очень формальные академические/педантические причины, которые редко играют какую-либо роль на практике. Но тем не менее.

В языке С (как и в С++) почти любой фундаментальный тип формально может иметь "запрещенные" представления, т.е. запрещенные комбинации битов. Такие запрещенные представления называются по-английски "trap representations". Если в программе какая-то переменная получит такое запрещенное представление, что чтение такой переменной формально приводит к неопределенному поведению, т.е. программа формально имеет право "упасть и взорваться".

Например, если мы возьмем указатель типа 'int *' и направим его на память, содержащую какие-то непредсказуемые случайные значения

C
1
2
char c[4] = { rand(), rand(), rand(), rand() };
int *p = (int *) c;
то может получиться так, что эти случайные значения в памяти сложатся в запрещенное представление для объекта типа 'int'. В такой ситуации если мы попытаемся прочитать значение '*p' из памяти, то поведение программы будет не определено. (Как я говорил выше, программа имеет право "упасть и взорваться".)

Другими словами, читать из памяти что попало через указатель типа 'int *' - опасно (опять же - из формальных академических соображений). Это относится и ко все другим типам, за исключением одного - 'unsigned char'. Тип 'unsigned char' гарантировано не имеет запрещенных представлений. Это - единственный такой тип. Т.е. через тип 'unsigned char' разрешается читать любое совершенно непредсказуемое содержимое памяти и вы гарантированно некогда не наткнетесь на запрещенное представление, потому что у типа 'unsigned char' их просто нет.

Поэтому для работы с произвольными бинарными данными рекомендуется использовать именно 'unsigned char'.
1
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 09:13  [ТС]
C++
1
2
3
4
5
6
7
typedef const unsigned char* bin_t;
 
template<typename T>
inline bin_t bin(const T& value)
{
    return reinterpret_cast<bin_t>(&value);
}
Цитата Сообщение от Dark Byte Посмотреть сообщение
а что по сериализации подскажете?
?????????????????????????????
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
07.11.2014, 09:19
TheCalligrapher, что это за запрещённые представления для int? Впервые слышу. Пример, приведи.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 09:29  [ТС]
хмм а с динамической памятью кстати такой номер почему то не проходит...
C++
1
2
3
4
5
int* value = new int;
*value = 123;
bin_t buff = bin(value);
int x = *reinterpret_cast<const int*>(buff);
delete value;
как я понял в x опять записывается указатель на value... почему только не ясно, ведь разыменование же... кстати со статичной переменной все прокатывало...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 09:45
Цитата Сообщение от nmcf Посмотреть сообщение
что это за запрещённые представления для int? Впервые слышу. Пример, приведи.
Какой еще "пример"?

Я же ясно сказал: спецификация языков С и С++ формально допускает существование "запрещенных" комбинаций битов для всех типов, кроме 'unsigned char'. Это не значит, что такие комбинации встречаются на повседневных практических платформах для типа 'int'.

Цель такой спецификации trap representation - допустить существование платформ, которые, например, хранят в данных дополнительные "проверочные" признаки. Например, платформы с явно хранимым битом четности. Если бит четности содержит "неправильное" значение, т.е. если данные не проходят проверку по четности, то такое представление является trap representation.

Обыкновенная платформа с 32-битным 'int' и представлением отрицательных чисел через "дополнение до 2" имеет право ограничить диапазон типа 'int' как [-2147483647, 2147483647], а значение '-2147483648' (0x80000000) зарезервировать, как запрещенное.

И т.д. и т.п.

Можно также упомянуть платформу ia64 (Itanium). Там если целочисленная переменная представлена регистром, то такой регистр может получить особенное значение - NaT (например, если переменная не инициализирована или если она прочитана из недоступной памяти). NaT на Itanuim - классический пример trap representation.
2
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
07.11.2014, 10:00  [ТС]
ЛЮДИ !!! 2 вопроса пожалуйста ответьте уже !!!!!

1. почему не срабатывает обратное преобразование, если память выделялась динамически (точнее срабатывает, но в переменную записывается адрес, несмотря на разыменование)
2. как быть с сериализацией? (описывал выше)

Добавлено через 3 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef const unsigned char* bin_t;
 
template<typename T>
inline bin_t bin(const T& value)
{
    return reinterpret_cast<bin_t>(&value);
}
 
template<typename T>
inline void unbin(bin_t buff, T& value)
{
    value = *reinterpret_cast<const T*>(buff);
}
это не работает
C++
1
2
3
4
5
6
int* value = new int;
*value = 123;
bin_t buff = bin(value);
int x;
unbin(buff, x);
delete value;
это работает
C++
1
2
3
4
int value = 123;
bin_t buff = bin(value);
int x;
unbin(buff, x);
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
07.11.2014, 10:06
Цитата Сообщение от Dark Byte Посмотреть сообщение
1. почему не срабатывает обратное преобразование, если память выделялась динамически (точнее срабатывает, но в переменную записывается адрес, несмотря не разыменование)
Я не понимаю, в чем проблема.

Вы написали функцию 'bin', которая возвращает указатель на ее аргумент. Теперь вы делаете вот это

C++
1
2
3
4
5
int* value = new int;
*value = 123;
bin_t buff = bin(value);
int x = *reinterpret_cast<const int*>(buff);
delete value;
В этом случае функция 'bin' возвращает указатель на 'value', т.е. фактически указатель на указатель: 'buff' физически указывает на указатель 'value'.

'reinterpret_cast' выше читает значение указателя 'value', интерпретируя его память как объект типа 'int'. В результате в 'x' ложится содержимое 'value' (проинтерпретированное в памяти как 'int'). Это численное значение адреса, возвращенное когда-то 'new' (возможно урезанное).

А что ожидалось то?

Добавлено через 1 минуту
Цитата Сообщение от Dark Byte Посмотреть сообщение
это не работает
это работает
Еще раз: в одном случае 'value' - это 'int'. В другом случае 'value' - это указатель на 'int'. Это совершенно разные вещи, не имеющие между собой ничего общего.

Разумеется, код будет работать по разному.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.11.2014, 10:06
Помогаю со студенческими работами здесь

reinterpret_cast<...>(...)
Всем привет! Сразу к делу. ВОПРОС: Как преобразовать переменную типа float в указатель типа double; КРАТКОЕ ОПИСАНИЕ...

По функции reinterpret_cast
Доброго времени суток, коллеги! Навоял вот такой код: #include&lt;iostream&gt; using namespace std; int main() { ...

Преобразование (reinterpret_cast)
ifstream infile(&quot;person.dat&quot;, ios::binary); infile.read(reinterpret_cast&lt;char*&gt;(&amp;pers),sizeof(pers)); pers - объект класса. ...

Оператор reinterpret_cast
#include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int main() { int x3 = -0x00260305; cout &lt;&lt;hex &lt;&lt;...

Reinterpret_cast и указатели
Добрый вечер. Есть вот такая конструкция: *reinterpret_cast&lt;Offsets::UnitGender*&gt;(pPlayerFields + Offsets::Unit::Gender) =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru