право компилятор напихать че своего в начало памяти занимаемой экземпляром класса, в его середину.
Перемешать поля местами и тп?
Имеет. Паддинг, выравнивание
Паддинг в расчет не берем - его можно руками задать вроде и точно знать.
Перемешать поля может, но это если такой компилятор или если установлен макрос #pack, в gcc по умолчанию не мешает местами
Это опять мимо стандартных , как это -- ХОРОШИХ в общем программ. #pack -- это прагма, НЕ стандартная.
ГЛАВНОЕ: нафига так бегать в структуре от байта к байту, если можно достаточно легко вычислить байтовое смещение каждого члена структуры относительно базового адреса, и уже по этому смещению обращаться?
взаимодействие между устройств.
Да нет уже и - понятно. Просто так бы пихал побайтно от и до конца. А так надо морочится.
чё там морочится? написал один раз функцию вычисляющую смещение мембера -- и всё. Да и наверняка есть такая уже либо в бусте, либо в стандарте
Ок, тогда если допустим, есть тип void*, метод принимает этот тип. И чтобы распарсить этот тип как структуру, то есть вытащить данные из void* в другие переменные. То здесь ведь будет работать способ (база + sizeof(тип)) и так далее присваивать и прибавлять?
Это вообще невозможно, *(void*) -- не тип
Точнее указатель), то есть при вызове метода подавался как (void*)структура.
И вообще что это значит распарсить этот тип как структуру -- структура не текст, чтобы её парсить. Это уже готовая форма в памяти
Имеется в виду создать прототип структуры с другим именем, то есть мы не знаем имя предыдущей, только порядок типов, и в нее считать данные используя в основе только указатель void* и смещение.
Это нарушение ODR, между прочим... ==> UB
Это не про ODR, но всё равно UB
Как не про ODR? Тип был один, а тут этот же образ объекта в памяти мы будем обрабатывать как другой тип
Ну это не про ODR, ODR это если бы имя у типа было одно, а поля разные
Ты очень узко трактуешь....
если это нарушение odr, то чем будет нарушение strict aliasing?
Ну, если он угадает с адресом члена данных, а с типом не угадает , вот будет оно
и когда он не угадывает с типом, то «тип был один, а тут этот же образ объекта в памяти мы будем обрабатывать как другой тип»
В начало нет. Перемешивать секции между собой имеет, всталять что-то между секциями имеет
Только не void* - как минимум unsigned char, UB ибо в общем случае как оно лежит в памяти решает компилятор и ни кто не гарантирует одно и то же поведение на каждой существующей в природе платформе.
Порядок байтов, правила выравнивания, даже размер integer зависят от платформы.
Еще раз: как это с кастом в void* связано?)
На конкретной платформе зная внутреннее устройство платформы, памяти и процессора платформы работать можно. В стандарт все случаи записать нельзя - по этому UB
Каст T* -> void* (если T является object type) никакого уб не имеет
А обратно и потом ходить по структуре?
Обратно тоже defined
Нет, в общем случае (если байты брались извне).
Каст T*->void*->T* определен в рамках одной платформы.
Если байты брались извне, никакого объекта там нет и говорить не о чем
Штука в том, что как оно выглядит в памяти исключительно на совести разработчика компилятора и просто так ходить по нему можно, но только если точно знаешь что делаешь. Причем ходить по void* нельзя (какой у void размер?).
Про ходьбу по воид никто не говорил. Никто не говорил, что прибавив N байт к началу ТС получит нужное поле на всех платформах
Вопрос был про реордеринг, ответ вроде как получен
Тогда уж implementation defined было бы более подходящим...
Да, скорее всего так. UB это скорее для случаев когда неизвестно что будет происходить даже в рамках одной платформы.
Но у меня есть опасения что в стандарте это всё UB без вариантов...
Обсуждают сегодня