2016-06-13 2 views
1

Согласно type aliasing rules, я предполагаю, что:reinterpret_cast преобразования цепи правильность

1) прямое преобразование uint64_t* в uint32_t* - это неправильно (я не могу получить доступ к данным через результат PTR и убедитесь, что я. получите правильное значение)

цепи 2) преобразования является OK (я могу безопасно получить доступ к данным)

uint64_t* -> unsigned char* -> uint32_t* 

uint64_t* -> void* -> uint32_t* 

Я правильно понимаю правила или нет?

Я всегда предпочитаю использовать союз s вместо этого, чтобы предотвратить возможные ptr. (что может привести к повреждению данных), но это не всегда возможно (и хорошо) решение.

+4

Нет, переинтерпретация указателя char в качестве указателя на тип, который не является фактическим типом, является UB, поэтому ваша цепочка не работает. –

+3

Также использование союза для достижения того же результата (ов) является UB. –

+0

Странно, что раздел cppreference [Type aliasing] (http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing) говорит только о полиморфных объектах. –

ответ

1

цепи 2) преобразования в порядке (я может безопасно получить доступ к данным)

uint64_t* -> unsigned char* -> uint32_t* 

uint64_t* -> void* -> uint32_t* 

Am я понять правила правильно или нет?

Номер A Прикованный reinterpret_cast как это будет не вернее прямого reinterpret_cast.

Я всегда предпочитаю использовать союзы вместо

Тип каламбуров с профсоюзом также нарушает правила наложения спектров.


Если у вас есть указатель на uint64_t, и вы хотите использовать четыре из восьми байт (я предполагаю, что на 8 битные байты), содержащихся в объекте и интерпретировать их как uint32_t, то вы должны сначала решить, какой из восьми байтов вы хотите использовать. В конце концов, все восемь из них не будут вписываться ни в один uint32_t. Вам нужны байты нижнего порядка или байты верхнего порядка? Или, может быть, что-то более экзотическое, как каждый байт? Также рассмотрите, в каком порядке должны быть байты в полученном uint32_t.

Если вы хотите, чтобы определенные байты основывались на их значении, то переносным способом является использование бит-сдвигов и масок.

Если вам нужны определенные байты на основе их положения в памяти, то переносным способом является использование std::memcpy.

+1

«** переносимый способ чтения правильных байтов - использовать бит-сдвиги и маски **» - как я вижу, маска _0xFF_ принесет мне _Least Significant Byte_, который лежит на _lowest_ addr. в машине _little-endian_, противоположной в _big-endian_, поэтому та же маска будет нацелена на diff. байт памяти. Поправьте меня если я ошибаюсь. –

+0

Альтернативой будет «memcopy», который вы хотите получить в принимающей переменной. –

+1

@AmaboCarab правильный. Маскировка дает вам младший байт, независимо от его сущности. – user2079303

-1

Если вы уверены, что ваша машина является либо большой, либо малой величиной endian (что почти всегда имеет место), вы можете использовать htonl() для определения сущности. На обеих архитектурах uint64_t можно рассматривать как uint32_t [2], это просто порядок байтов, который отличается. Таким образом, вы можете reinterpret_cast и добавить смещение на основе endianness. В то время как это нестандартно, существует только одна возможная реализация большого эндиана и малочисленного принципа (принцип пигментных отверстий). Обратите внимание, что это не будет работать, например. архитектуры среднего уровня (которые являются редкими, но существуют) или любой архитектурой, где невозможно определить сущность.

+1

Архитектуры среднего уровня не являются * мнимыми *, но, возможно, достаточно редко эти дни игнорируются. – user2079303

+0

Да, извините за то, что они придумали воображаемую. – lorro

+0

Исправлено так, что позже читатели находят правильный ответ. – lorro

Смежные вопросы