1 frag / 2 deaths
> А как решен вопрос ссылок в языке Ü?
Мы не знаем, что такое "ссылки в языке Ü", но на всякий случай советуем жителям приполярных регионов в зимнее время избегать орального контакта с охлажденными металлическими предметами.
nes
> А чо std::is_arithmetic для bool, char, wchar_t, char8_t, char16_t, char32_t возвращает Ъ, он пьян?
А с каких это пор эти типы перестали быть арифметическими? Я еще могу понять недоумение по поводу всяких новых "char8_t, char16_t, char32_t"... но дорогие нам с самого детства bool, char, wchar_t являлись арифметическими еще с времен царя Гороха.
Особенностью bool, char, char16_t, char32_t, wchar_t является то, что они формально (по стандарту) не относятся ни к классу знаковых, ни к классу беззнаковых целых типов, то есть входят в класс целых отдельной независимой группой. Однако при этом предикаты std::is_signed и std::is_unsigned рапортуют фактическую знаковость этих типов, то есть результаты этих предикатов игнорируют формальную классификацию из стандарта языка.
Korben_Dallas
В чем ценность 'A' + 'B' или true + false?
nes
> В чем ценность 'A' + 'B'
Ну это очень часто
if ( s >= '0' && s <= '9' ) {
digit = s - '0';
...
}if ( *s >= 'a' && *s <= 'z' ) {
*s = *s - 'a' + 'A';
...
}nes
> или true + false?
x = x + delta * flag;
nes
Ну, во-первых, я думаю, не надо объяснять, что в С и С++ как не было, так и нет "настоящего" символьного типа. Все символьные типы - это просто "маленькие" целые типы.
Во-вторых, классовая особенность арифметических типов в спецификации языка не сводится только к "школьным" арифметическим операциям, а включает также операции упорядочивающего сравнения. Ценность этих операций для символьных типов, я думаю, объяснять не нужно.
В-третьих, 'A'+'B' может и выглядит странно, но '5'-'0' - совсем нет. Да и полезность арифметики над булевским типом с целью написания branchless кода тоже трудно переоценить.
В godbolt добавили "Claude Explain"
Я тестирую все ИИшныцы простым вопросом:
Here a short and simple program in C programming language:
int main(void)
{
int a;
0 ? a = 1 : a = 2;
}
However, this program is invalid. Can you spot and explain the problem from the point of view of the standard C language?
Практически все они сразу же бросаются отвечать, что программа является синтаксически корректной, но согласно приоритету операторов выражение в коде парсится как `(0 ? a = 1 : a) = 2` и ошибка заключается в том, что здесь получается присваивание в rvalue.
Однако такой ответ - бред сивой кобылы, согласно стандартному С. В реальности правильный ответ: данное выражение вообще невозможно распарсить в стандартной грамматике языка С. То есть это просто синтаксическая ошибка.
Единственный ИИ, который с первой попытки сразу мне дал правильный ответ - Yandex AI. Следующий результат у DeepSeek - он изначально выдал бред, но тут же без остановки продолжил рассуждения и сам же поправился.
Все остальные (ChatGPT, Gemini, Copilot, Grok, ...) сразу выдают вышеупомянутый неправильный ответ про rvalue и останавливаются. Приходится дополнительно, хитро прищурившись, просить их построить дерево парсинга и только тогда они в конечном итоге "посыпают голову пеплом" и заявляют, что их исходный ответ был неправильным. Причем некоторые (ChatGPT) сначала еще пытаются генерировать ложные деревья, выдумывая несуществующие синтаксические правила.
Вот попробовал Claude Sonnet 4.6 только что (не в Godbolt, а прямо на claude.ai) - то же поведение. В итоге: "...I was wrong in my previous answer. The problem is not a semantic one (assigning to an rvalue) — it is a syntax error, a pure grammar violation. The token = 2 after the third operand a simply cannot be reduced under any production rule. There is no valid parse tree for this expression under the C standard grammar."
Korben_Dallas, наверное можно и через приоритеты объяснить, только приоритеты надо выводить из грамматики.
Если следовать этой грамматике:
https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
, то наименее приоритетной операцией будет перечисление-запятая (терм expression, как непустой вариант expression-statement), в данном выражении отсутствующая
Следующие по приоритету - операции присваивания assignment-expression (вариант с наличием assignment_operator, правоассоциативный)
И уже только следующим приоритетом будет conditional-expression (вариант с наличием знака вопроса и двоеточия) - этот вариант не получается, т.к. в терме с вопросом отсутствует двоеточие.
То есть, если следовать этим приоритетам, то разбор выражения получается такой:
(0 ? a) = ( (1 : a) = 2 )
Естественно,
0 ? a
и
1 : a
уже никаким операциям не соответствуют (второе могло бы соответствовать термам struct_declarator или labeled_statement, но только не внутри выражения).
Интересно, кстати, почему в справочниках пишут, что приоритеты операторов присваивания и тернарного оператора одинаковы, когда из грамматики получается не так?
Грамматику выражения невозможно полностью описать приоритетами. Во-первых, грамматика зацикливается через взятие в скобки. Во-вторых, в С грамматика оператора `?:` малость замысловата и, поэтому, вообще никак не впихуема в линейную последовательность "приоритетов".
Поэтому "приоритеты" - это просто более-менее удобочитаемая шпаргалка, суррогатный заменитель грамматики. (Студенткам, чтобы было что на бедре перед экзаменом писать.) А в формальном языке нет никаких "приоритетов". Есть только грамматика.
Либо грызите гранит грамматики. Либо получится вот такая бнопня, как у вас получилась выше.
Korben_Dallas
> Либо грызите гранит грамматики
Проще уволить тех, кто пишет длинные выражения, которые нельзя разобрать через приоритеты. Вместе с теми, кто пишет объявления как в #19937. Потому что это вредительство :)
Есть прога под ZX Spectrum на ассемблере. В проге используются данные, которые генерятся в виде бинарных или .asm-файлов, которые в конце компилируются вместе с основным кодом в один исполняемый бинарник. Если в данных есть ссылки на какие-то другие данные или процедуры кода - такие данные генерятся в виде .asm-файла с db/dw и метками вместо конкретных значений.
Компиляция и генерация данных осуществляются на обычном компе, с помощью кросскомпилятора и скриптов на питоне.
Линкера и аналогов .obj-файлов нет, да и не помог бы мне линкер в той задаче, которая у меня возникла - мне надо запаковать данные и распаковывать их в рантайме, чтоб уменьшить размер бинарника. С инструментами запаковки/распаковки проблем никаких нет, их полно понаписано.
НО ВОТ ПРОБЛЕМА: значение меток доступны только в процессе компиляции, поэтому я не могу запаковать данные со ссылками, т.к. они в виде .asm-файла, который сначала необходимо скомпилировать. Но мне надо запаковать эти данные до компиляции итогового бинарника. Замкнутый круг.
Ситуация еще осложняется тем, что запаковка/распаковка идет не одним куском, а несколькими, т.к. у разных видов данных разная энтропия, и одним куском они жмутся хуже, чем суммарно по-отдельности.
ПОка придумал решение с менеджером ресурсов - утилитой и модулем для скриптов, который ведет учет размещения ресурсов и всех меток в базе данных, позволяя генерировать данные, ссылающиеся на уже сгенеренные данные (т.к. метки сохранены в базе данных). Перед компиляцией менеджер создает .asm-файл с определениями меток, и этот файл инклюдится в итоговой компиляции.
Но это рещение не позволяет ссылаться на процедуры, адреса которых станут известны только после компиляции. И к тому же мне не нравится, что я должен заранее задать хотя бы стартовый адрес секции ресурсов, и только потом при компиляции ориентироваться на получившиеся адреса ресурсов. А значит расположение кода должно подстраиваться под размещение ресурсов, но меня это не устраивает, мне нужно, чтоб код располагался в нижней части адресного пространства.
Что бы еще придумать?
Dmitry_Milk
> Что бы еще придумать?
Да уж куда еще придумывать то, и так уж такое придумать... да жизнь явно не скучно проходит ))
stratego, я имел в виду, как бы элегантнее решить проблему.
В лоб я могу просто руками все делать. Скомпилировать без компресии, как раньше, то есть получить итоговый имидж такой, какой он должен получиться после рантайм-распаковки. Потом посмотреть в листинге адреса, выдернуть из имиджа нужные куски, запаковать, и потом в коде лоадера-распаковщика вручную вбить адреса, куда распаковывать.
Но так же никуда не годится, любое изменение ресурсов - и мне всю эту ручную работу опять заново делать.
Похоже на написание вируса...
Надо свой инструментарий по ходу писать... который будет делать, всё что делается в ручную. Хотя что-то про сжатые исполняемые файлы когда то читал... но уже не помню ничего, такое сейчас ради фана только. Никого не пугают даже гигабайтные файлы ((