Size: a a a

2020 December 07

VS

Vlad Serebrennikov in pro.cxx
Konstantin Osipov
Вроде как договорились, что если два типа - similar, то можно один читать через другой? (читать например int через указатель на unsigned int можно)
это значит совсем не то, что compatible в си
http://eel.is/c++draft/conv.qual#2
источник

LA

Liber Azerate in pro.cxx
Konstantin Osipov
Вроде как договорились, что если два типа - similar, то можно один читать через другой? (читать например int через указатель на unsigned int можно)
Читать можно если тип является char, unsigned char либо std::byte, либо динамический тип
источник

VS

Vlad Serebrennikov in pro.cxx
Liber Azerate
Читать можно если тип является char, unsigned char либо std::byte, либо динамический тип
или через соответствующий (без)знаковый тип
источник

LA

Liber Azerate in pro.cxx
Vlad Serebrennikov
или через соответствующий (без)знаковый тип
Ну да, это я опустил как незначительное и само собой разумеющееся
источник

VS

Vlad Serebrennikov in pro.cxx
http://eel.is/c++draft/basic.lval#11
на всякий случай вот пункт про strict aliasing в стандарте
источник

KO

Konstantin Osipov in pro.cxx
в данном https://en.cppreference.com/w/cpp/language/reinterpret_cast тексте есть "unless one of the following is true"
источник

KO

Konstantin Osipov in pro.cxx
вот поэтому и не хватает тупо таблички что через что можно читать, а что нельзя
источник

h

hazer_hazer in pro.cxx
Vlad Serebrennikov
нет, такое можно только через bit_cast
а. да. только копированием байтов
источник

VS

Vlad Serebrennikov in pro.cxx
Konstantin Osipov
вот поэтому и не хватает тупо таблички что через что можно читать, а что нельзя
T
signed T
unsigned T
char
unsigned char
std::byte

такой?
источник

KO

Konstantin Osipov in pro.cxx
за исключением того, что это не табличка - да
источник

KO

Konstantin Osipov in pro.cxx
мне из прочитанных тонн материала не было очевидно, что читать int64_t через int32_t*, int16_t* - нельзя, а через int8_t* - можно.
источник

KO

Konstantin Osipov in pro.cxx
(мне это до сих пор неочевидно, зачем так сделали).
источник

LA

Liber Azerate in pro.cxx
Konstantin Osipov
мне из прочитанных тонн материала не было очевидно, что читать int64_t через int32_t*, int16_t* - нельзя, а через int8_t* - можно.
И то, последнее – необязательно. Только если оно реализовано через char
источник
2020 December 08

m

magras in pro.cxx
Konstantin Osipov
(мне это до сих пор неочевидно, зачем так сделали).
Если функция пишет по произвольному указателю на T, она инвалидирует все закешированные значения T, потому что возможно мы только что изменили одно из них. Если мы пишем в char* мы вынуждены инвалидировать закешированные значения _всех_ типов, потому что мы могли изменить любой из них. Тоже самое происходит и в обратном направлении: при записи по любому указателю мы инвалидируем все буферы char.

Поэтому работа с char накладывает штрафы на производительность. Поэтому строки уводят от использования char в сторону char8_t, а для сырых данных предлагают использовать std::byte.
источник

m

magras in pro.cxx
Это несколько упрощенное описание, но должно передать идею стоящую за strict aliasing'ом и почему он полезен. Примером инвалидации будет повторное вычитывание значения из памяти хотя оно у нас уже есть в регистре.
источник

KO

Konstantin Osipov in pro.cxx
magras
Если функция пишет по произвольному указателю на T, она инвалидирует все закешированные значения T, потому что возможно мы только что изменили одно из них. Если мы пишем в char* мы вынуждены инвалидировать закешированные значения _всех_ типов, потому что мы могли изменить любой из них. Тоже самое происходит и в обратном направлении: при записи по любому указателю мы инвалидируем все буферы char.

Поэтому работа с char накладывает штрафы на производительность. Поэтому строки уводят от использования char в сторону char8_t, а для сырых данных предлагают использовать std::byte.
в данном случае речь идёт о чтении, а не записи. Мы берём и читаем int64_t* как два int32_t*, ну или читаем int8_t* как int64_t*. Мы ничего не пишем.
источник

m

magras in pro.cxx
Konstantin Osipov
в данном случае речь идёт о чтении, а не записи. Мы берём и читаем int64_t* как два int32_t*, ну или читаем int8_t* как int64_t*. Мы ничего не пишем.
Если мы ничего не писали в i64, значит мы можем не перечитывать его значение из памяти. Мы ведь писали только в пару i32. В результате у нас "потеряется" запись.
источник

ПК

Побитый Кирпич... in pro.cxx
Konstantin Osipov
в данном случае речь идёт о чтении, а не записи. Мы берём и читаем int64_t* как два int32_t*, ну или читаем int8_t* как int64_t*. Мы ничего не пишем.
Иногда может работать, УБ от этого никуда не девается
источник

m

magras in pro.cxx
Кстати я понял что был не прав в том, что С++20 не поможет. Там же memcpy теперь неявно создает объекты, поэтому в 20ом стандарте оригинальный пример должен работать правильно в случае если int8_t это char.
источник

B

Bulat in pro.cxx
🌚
источник