char * правила преобразования и наложения - PullRequest
5 голосов
/ 19 декабря 2011

Согласно строгим правилам алиасинга:

struct B { virtual ~B() {} };
struct D : public B { };

D d;
char *c = reinterpret_cast<char*>(&d);

A char* для любого объекта другого типа действуетНо теперь вопрос в том, будет ли он указывать на тот же адрес & d?Какова гарантия C ++ Standard, что он вернет тот же адрес?

Ответы [ 3 ]

6 голосов
/ 19 декабря 2011

c и &d действительно имеют одно и то же значение, и если вы переинтерпретируете приведение c обратно к D*, вы получите действительный указатель, который вы можете разыменовать. Кроме того, вы можете рассматривать c как (указатель на первый элемент) непрозрачного массива char[sizeof(D)] - это действительно основная цель приведения указателей к указателям на символы: разрешить (де) сериализацию (например, ofile.write(c, sizeof(D));) , хотя обычно это следует делать только для примитивных типов (и их массивов), поскольку двоичная компоновка составных типов обычно не указывается переносимым образом.

Как правильно заметил @Oli и хотел бы, чтобы я подтвердил, вам никогда не следует сериализовать составные типы в целом. Результат почти никогда не будет десериализуемым, поскольку реализация полиморфных классов и заполнения между полями данных не указана и недоступна для вас.

Обратите внимание, что reinterpret_cast<char*>(static_cast<B*>(&d)) может рассматриваться как непрозрачный массив char[sizeof(B)] по аналогичным рассуждениям.

2 голосов
/ 19 декабря 2011

Раздел 5.2.10, пункт 7 стандарта C ++ 2003 года гласит:

Указатель на объект может быть явно преобразован в указатель на объект другого типа.За исключением того, что преобразование r-значения типа «указатель на T1» в тип «указатель на T2» (где T1 и T2 являются типами объектов и где требования к выравниванию T2 не являются более строгими, чем требования к T1) и обратно к егоИсходный тип возвращает исходное значение указателя , результат такого преобразования указателя не определен.

Если под «тем же адресом» вы подразумеваете «исходное значение указателя», то эта запись говорит «да». "

0 голосов
/ 19 декабря 2011

Цель ясна (а не то, что нужно обсуждать):

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

Формулировка стандарта не отражает этого, но это не означает, что здесь есть реальная практическая проблема.

char *c = reinterpret_cast<char*>(&d);

c будет указывать на первый байт d, всегда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...