Информация об изменениях

Сообщение Re: Это UB ? от 01.07.2024 15:59

Изменено 01.07.2024 16:00 vsb

Re: Это UB ?
Здравствуйте, LaptevVV, Вы писали:

LVV>А сейчас ?

LVV>Где-то у меня в мозгах зацепилось, что это UB.

И сейчас UB. Хотя, наверное, работать везде будет. Но по правилам — в юнионах можно читать только те поля, куда ранее была запись.

LVV>Размещающий new — не предлагать

LVV>reinterpret_cast — можно попробовать.

LVV>variant ?

LVV>Что-то не совсем то, что мне нужно.

Могу ошибаться, но вроде можно прикастовать int* к char*. В С это должно работать, насчёт С++ не уверен. Тут, правда, тоже нюансы могут быть типа сколько там байтов в int и сколько битов в char — тоже величины не определённые.

А так — 100% правильный вариант это битовая арифметика. Хороший компилятор должен распознать замысел и преобразовать всё в ожидаемый код.

Вот пример с godbolt:

void u32to8(uint32_t u32, uint8_t *u8) {
    u8[0] = u32 & 0xff;
    u8[1] = (u32 >> 8) & 0xff;
    u8[2] = (u32 >> 16) & 0xff;
    u8[3] = (u32 >> 24) & 0xff;
}


Это скомпилировалось в

u32to8(unsigned int, unsigned char*):
        str     r0, [r1]  @ unaligned
        bx      lr
main:


То бишь в одну инструкцию. А когда компилятор это инлайнит по месту вызова, там вообще ничего не остаётся.
Re: Это UB ?
Здравствуйте, LaptevVV, Вы писали:

LVV>А сейчас ?

LVV>Где-то у меня в мозгах зацепилось, что это UB.

И сейчас UB. Хотя, наверное, работать везде будет. Но по правилам — в юнионах можно читать только те поля, куда ранее была запись.

LVV>Размещающий new — не предлагать

LVV>reinterpret_cast — можно попробовать.

LVV>variant ?

LVV>Что-то не совсем то, что мне нужно.

Могу ошибаться, но вроде можно прикастовать int* к char* (но не наоборот). В С это должно работать, насчёт С++ не уверен. Тут, правда, тоже нюансы могут быть типа сколько там байтов в int и сколько битов в char — тоже величины не определённые.

А так — 100% правильный вариант это битовая арифметика. Хороший компилятор должен распознать замысел и преобразовать всё в ожидаемый код.

Вот пример с godbolt:

void u32to8(uint32_t u32, uint8_t *u8) {
    u8[0] = u32 & 0xff;
    u8[1] = (u32 >> 8) & 0xff;
    u8[2] = (u32 >> 16) & 0xff;
    u8[3] = (u32 >> 24) & 0xff;
}


Это скомпилировалось в

u32to8(unsigned int, unsigned char*):
        str     r0, [r1]  @ unaligned
        bx      lr
main:


То бишь в одну инструкцию. А когда компилятор это инлайнит по месту вызова, там вообще ничего не остаётся.