- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 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.
тока он там переключица в Bignum или как оно тмм
а во втором Int и long были разными тупами с программным переключеним
потом стал PEP237
забавно что было такое предложегие: сделать union в котором лежит long (для инта) или массив из digit (для longа) на пару с long size;
отличалось по последнему биту: им пожертвовали ради совмещения.
соответствено sizeof врал, надо было проверять последний бит, и если он 1 то брать size.
к щастью, это говнорешение запороли
А такое решение довольно часто юзают для интерпретаторов.
В какой-то реализации лишпа вроде 2 бита откусывали.
как же можно сломать sizeof?
что вернет sizeof для этого униона?
да, но ее зарубили
а теперь представь что будет если такой union вернуть или передать в качестве оргумента
этот юнион может или представлять обычный Long или bignum.
тогда в length Хранится длина (в байтах)
а в digits хранятся данные
там может быть массив из 44х цифр
sizeof будет думаь что там одна цифра, Но по факту их 44
это можно только понять в коде пр length.
это слдомает sizeof
и такой union кроме как через указатель никак ине передать
может быть там число 222 представлено как 3 байта (digitа)
децилмал бинари энкодингш
то-есть digit вовсе не digit?
зы: а не, вру, Знал. Слака ставила питона и так я о нем узнал, но я на нем не писал конечно
если там колконвешнен такой что вызываетль создает в стеке структуру и передает ее указатель через EAX то все будет работать же внезапно? или ее попытаются скопировать в стек?
он же не умеет читать length
короче, чувак сломал к ухям частьс исечки
* передачу по значению
* sizeof
* массив из такой хуни тоже не сделать
байтоеб дегрейднул сисечеку почти до асемблера
Открою секрет, струкьуры в сишке фиксированного размера, никакой sizeof нигде тебе не будет читать поля структуры.
> передачу по значению
Жто же питно, в нём всё в куче, функции принимают только оказатели.
> массив из такой хуни тоже не сделать
указатели.
Еще раз попытаюсь донести свою мысль:
В сишке обычно структуры или юнионы имеют предсказуемый (получаемый через sizeof) размер
Приведенный мною пример это ХАК. По причине этого ХАКА с этой "структурой" (не сишкин термин а впринципе это структура данных -- кусок памяти) работать через sizeof нельзя
Если хак приносит профит - вай нот?
да ради яхве!
но я говорю что таким образом мы лишаем себя права использовать sizeof
вот я про это и говорю!!
Или он проходит по стандарту и так?
Что я вижу:
* Выход за границу массива
* Игнорирование перестановки полей структуры компилятором
* Игнорирование паддингов, в которые нельзя писать
Хотя, я всех тонкостей, разумеется, не знаю. Но, если учесть капризность стандарта и безумные правила для UB, любой другой код в аналогичной ситуации наткнулся бы на одну из этих проблем и улетел бы в UB.
А переставлять поля и так нельзя.
А теперь приведи мне свою реализацию где sizeof бы работал как ты кочешь.
то что его юзают как динамический это ХАК
блин!
кажется что я на другом языке говорю
да я не спорю что по другому никак
я всего лишь сказал что это ХАК
потому что чуваки хотят динамический массив не через указатель
ты согласен что это ХАК?
С чего ты это взял?
то что ее используют по другому это ХАК
то как рефлексия в Java или dynamic в C#. Это не стандартное использование языка
что не так?
>>>
Размер long + sizeof(digit), что не так?
но с помощью этой структуры описывают структуру БОЛЬШЕГО размера
то-есть sizeof с ней использовать нельзя
я это и называл словом ХАК
а это хак
+89
потому что указатель явно говорит что у нас тут просто указатель, а где реально лежат данные мы не знаем
а в случае массива из одного элемента они лежат дальше за структурой.
Короче может быть для бородатых сишников (типа Борманда) это и "идиома", но для меня это точно хак
Бородатым сишникам не нравится выделять по 2 куска памяти на каждый чих, поэтому и юзают такую хуйню для всяких строк, блобов да длинных чисел.
Вся суть в аллокации хедера и данных одним блоком. А идиома с массивом - просто для удобства, чтобы меньше кастовать. Можешь выкинуть массив и переименовать структуру в number_header.
З.Ы. Даже в крестах make_shared() делает нечто подобное чтобы склеить счётчики и объект в одну аллокацию.
именно потому (в 2001 году) они сделали не флекс аррей (gcc мог ине уметь тогда C99)
потом ты пишшеь
petuh p[42]
что будет?
бдует говно!! а значит еще и массивы изнего делать нельзя
Да похуй на UB, оно вообще не работает (отрицательное d засрёт своим знаковым битом всё остальное). Или у автора там беззнаковый чар?
Кстати, у некоторых кококомпиляторов есть переключатель «signed char/unsigned char».
Т.е. это на случай, когда пишут не signed char, не unsigned char, а просто char?
char разработан лишь на столько, чтобы вместить в себя 127 банок сгущенки
вместит-ли он 128ю зависит от покулятора
я рекомендую всегда явно писать сигнет или унсигнед
а еще лучше писать uint8_t