- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
// https://github.com/CVC4/CVC4/blob/14b9dbaa0c9e8dce52d1a28595dc1cc80756abed/src/expr/pickler.cpp
static Block mkBlockBody4Chars(char a, char b, char c, char d) {
Block newBody;
newBody.d_body.d_data = (a << 24) | (b << 16) | (c << 8) | d;
return newBody;
}
static char getCharBlockBody(BlockBody body, int i) {
Assert(0 <= i && i <= 3);
switch(i) {
case 0: return (body.d_data & 0xff000000) >> 24;
case 1: return (body.d_data & 0x00ff0000) >> 16;
case 2: return (body.d_data & 0x0000ff00) >> 8;
case 3: return (body.d_data & 0x000000ff);
default:
Unreachable();
}
return '\0';
}
// ...
void PicklerPrivate::toCaseString(Kind k, const std::string& s) {
d_current << mkConstantHeader(k, s.size());
unsigned size = s.size();
unsigned i;
for(i = 0; i + 4 <= size; i += 4) {
d_current << mkBlockBody4Chars(s[i + 0], s[i + 1],s[i + 2], s[i + 3]);
}
switch(size % 4) {
case 0: break;
case 1: d_current << mkBlockBody4Chars(s[i + 0], '\0','\0', '\0'); break;
case 2: d_current << mkBlockBody4Chars(s[i + 0], s[i + 1], '\0', '\0'); break;
case 3: d_current << mkBlockBody4Chars(s[i + 0], s[i + 1],s[i + 2], '\0'); break;
default:
Unreachable();
}
}
Очередное переизобретение какой-то байтоебской поеботы типа ntohl(). И вообще, тут UB.
P.S. s.size() >= std::numeric_limits<unsigned>::max() - 4 наверняка вылетит по памяти значительно раньше. Но "cover my ass" assert можно и вставить.
Что-то типа (uint32_t)a << 24 или static_cast?
Но int во-первых хуй знает какого размера. А во-вторых сдвиг знакового числа влево до упора ничем хорошим не закончится (даже при 32-битном инте).
UB существует только в «C» и «C++». В других языках программирования никаких UB нет, именно поэтому я за другие языки.
1) число знаковое и может быть отрицательным
2) его двигают влево
"UB" существует во всех низкоуровневых языках с претензией на переносимость и у которых больше одной реализации. Даже у разных процов линейки "x86" в некоторых ситуациях было разное поведение на разных процах (щас точно не помню все, помню что была хуита с чтением слова по адресу FFFF, в одних процах байт читался из следующего сегмента, в других из начала текущего, остальных нагуглить/наяндексить не могу, они советуют мне посмотреть "Свойства системы"), так в стародавние времена определяли на каком проце мы запущены.
UB хуже. С ним даже доки по железу и конпелятору тебе не помогут.
И, на самом деле, UB есть и во вполне высокоуровневых языках. Просто они там довольно очевидные. Гонки между потоками, к примеру.
Мда, надо бы как-нибудь выделить денёк, чтобы выспаться.
А уж в железе сколько UB'ов...
В первых пятивольтовых микросхемах ТТЛ входной сигнал в интервале от 2,5 вольт до 5 воспринимался как единица, от 0 до 0,5 вольт –— как ноль, а вот сигнал в интервале 0,5...2,5 вольт был UB.
А такое решение довольно часто юзают для интерпретаторов.
В какой-то реализации лишпа вроде 2 бита откусывали.
Открою секрет, струкьуры в сишке фиксированного размера, никакой sizeof нигде тебе не будет читать поля структуры.
> передачу по значению
Жто же питно, в нём всё в куче, функции принимают только оказатели.
> массив из такой хуни тоже не сделать
указатели.
Если хак приносит профит - вай нот?
Или он проходит по стандарту и так?
Что я вижу:
* Выход за границу массива
* Игнорирование перестановки полей структуры компилятором
* Игнорирование паддингов, в которые нельзя писать
Хотя, я всех тонкостей, разумеется, не знаю. Но, если учесть капризность стандарта и безумные правила для UB, любой другой код в аналогичной ситуации наткнулся бы на одну из этих проблем и улетел бы в UB.
А переставлять поля и так нельзя.
А теперь приведи мне свою реализацию где sizeof бы работал как ты кочешь.
С чего ты это взял?
>>>
Размер long + sizeof(digit), что не так?
Бородатым сишникам не нравится выделять по 2 куска памяти на каждый чих, поэтому и юзают такую хуйню для всяких строк, блобов да длинных чисел.
Вся суть в аллокации хедера и данных одним блоком. А идиома с массивом - просто для удобства, чтобы меньше кастовать. Можешь выкинуть массив и переименовать структуру в number_header.
З.Ы. Даже в крестах make_shared() делает нечто подобное чтобы склеить счётчики и объект в одну аллокацию.
Да похуй на UB, оно вообще не работает (отрицательное d засрёт своим знаковым битом всё остальное). Или у автора там беззнаковый чар?
Кстати, у некоторых кококомпиляторов есть переключатель «signed char/unsigned char».
Т.е. это на случай, когда пишут не signed char, не unsigned char, а просто char?