ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 марта
907980 Топик полностью
Связанные сообщения
CppMetaprogrammingTyping
Вы просто не умеете его готовить. Я бы мог бесконечно показывать примеры, но это непробиваемо. Сразу авторитетно докажут, что у ...2022-09-30
Embedded Template Library (iar arm 9.20.4)2022-05-18
Наброшу.2021-12-06
В C++ доступна вся C-библиотека. Когда C++ сам себе разумеется нет, а как ты себе представляешь? Можешь написать свою реализацию...2020-09-23
Ты хочешь static_if, которого в C++ в чистом виде нет. constexpr if это совсем не то, т.к. он неизбежно будет компилиров...2020-07-02
В общем случае может быть 2-3 подхода перечисленных ниже. В базе всегда SFINAE -- шаблон откидывается и просматриваются следующи...2020-07-02
Надо понимать, что класс -- это не структура. Применительно к C++ мне больше нравится слово тип. Тип -- это сущность существующа...2020-04-26
Я говорю про другую типизацию. Не про int или long, и даже не про int или char*. Программа на ООП-языке существует в рамкой неко...2019-12-19
C#, Java и тем более Javascript -- это совсем другой код, нежели C++. На порядок менее оптимальный, если конечно задача не своди...2019-12-19
С языком очень даже связано. Компилирующие языки со статической типизацией (C++, C#, Java, C, Pascal) пропускают гораздо меньше ...2019-12-17
Не совсем. C++ -- это уход в сторону _типизированных_ ЯВУ, а Java или C# -- подвижка в сторону "управляемого кода" и что наиболе...2019-11-03
Да конечно, ну вот расскажи, как оно работает -->2019-10-25
Мне какой-то куб для Renesas вспомнился, лет 6 тому назад. Они хвалились, что у них код компилится сразу, как его пишешь. В итог...2019-10-25
Увы, часто нет. Ардуины не просто так возникли. МК подросли и стали возможны другие подходы к разработке. Видно же что делается:...2019-03-03
С этого стоило и начинать. С того, что язык скриптовый. И это уводит совсем в другую сторону, практически в параллельную вселенн...2019-03-01
Для этого просто существуют разные языки! Смотри вторую ссылку: 2017-11-29
Утиная типизация - это оно? -> -->2017-11-28
EvgenyCD! Смотри ссылку! Я понял, что это круче чем swig, например, в определённых обстоятельствах. Правда руки применять надо...2017-02-09
Это свойство практически любого языка с динамической типизацией. Здесь питон притянут за уши. Но это НЕГАТИВНОЕ свойство для бол...2010-01-13
fk0, легенда (03.03.2019 15:39, просмотров: 724) ответил Ксения на Ваша классификация языков программирования точь-в-точь такова, как классификация животных из древне-китайской энциклопедии: :)
Не соглашусь, во-первых я чётко подвёл к мысли, что возможны разные классификации, существование одних не запрещает другие. И если смотреть под разными углами -- можно видеть разные свойства. Языки с динамической типизацией и со статической явно имеют значимые отличия, например. А при делении на процедурные и непроцедурные языки этих отличий не видно. Вот толк от другой классификации. И если разделять на процедурные и непроцедурные языки, то здесь тоже всё очень непросто становится. Начиная с того, что обычный C может начинать проявлять признаки непроцедурного языка при необходимости, ввиду как раз (мета)программирования на макросах. Где программист понятия не имеет в какие конструкции оно выродится в конечном счёте. И уж в C++ можно совершенно точно создание таких программ, когда программист не знает решения, и его находит компилятор в процессе компиляции и генерации программы. Элементарный пример: вычисление логарифма (чисел Фиббоначи, на чего угодно ещё) на шаблонах. Программист не знает какую циферку вписать и поручает это компилятору. А может и не знать какие именно функции применить и тоже поручить это компилятору. Собственно это происходит каждый раз, когда применяются user defined conversion operators и implicit conversion. Могут быть и более сложные примеры, когда задан в общем случае некий набор правил, но каждый частный случай не программируется руками, а выводится по заданным правилам. Можно, конечно, сказать, что мол это всё ещё задание последовательности инструкций... Но по крайней мере программист уже явно не задаёт сам эту последовательность инструкций. Дальше больше, можно взять обычный Pascal, стандартный, ISO 7185:1990. И написать на нём интерпретатор какого-либо другого языка программирования. Что проще: есть миниатюрные лиспы, есть миниатюрный tcl... И на последнем уже реализовать основную логику программы. И тоже получается интересная история, последовательности исполняемых инструкций ограничены весьма небольшим множеством (код интерпретатора), а пространство возможных программ при это устремляется в бесконечность. Или, например, Forth, то же самое. Последовательности исполняемых инструкций ограничиваются интерпретатором шитого кода и кодом базовых функций. Число которых что в Forth, что в Lisp, умеет сводиться к очень малому количеству, порядка пары десятков. А программы-то могут быть какие угодно сложные. Здесь конечно тоже можно сказать, мол раз программа теперь задана в других инструкциях, то вот мол инструкции на этом языке явно заданные. Но с другой стороны, см. ниже, программист может заведомо не знать это последовательность, т.к. он может быть зависима от входных данных. Но что тогда называть непроцедурным языком? 1) язык, который по заданным правилам находит решение в момент компиляции и формирует код (программист лишь задаёт логические правила, по которым находится решение, в виде шаблонов, например), ту же последовательность инструкций... 2) язык, который по заданным правилам находит решение в момент исполнения (для данных заданных в момент исполнения тоже), не знаю нужно ли тут уже генерировать код. Если второе, то это типичный язык логического программирования. Prolog. Но нужен ли здесь вообще специальный язык? Скорей нет. Потому, что язык программирования должен оперировать программой получаемой в момент компиляции, а не данными получаемыми в момент исполнения. Последнее может быть реализовано библиотекой, на любом языке программирования. В конечном счёте получаются, все языки задают последовательность действий для процессора? Нет. Как я изначально и сказал, последовательность действий для процессора формируется компилятором, для какой-то локальной части программы. Например, в пределах функции. На глобальном уровне ни компилятор, ни программист могут не знать какие функции будут вызываться (это вычисляется в момент выполнения), с какими аргументами (зависящими от входных данных), и как это повлияет на ход выполнения программы. Он линейный может быть только в каком-то маленьком кусочке функции -- вот где последовательность. Более того, сам порядок вычислений он же часто не определён жёстко, могут применяться ленивые вычисления, динамическое программирование, параллельное вычисление на разных ядрах. Это в языках C или Pascal совершенно напрасно введено понятие "последовательности вычислений", совершенно глупо и на ровном месте навязывающее последовательность там, где её нет (если вычисления, например, между собой никак не зависимы). В Lisp, например, для этого существует функция begin, для принудительного вычисления своих аргументов слева-направо. Конечный автомат не является антиподом, это опять же одна и то же сущность, но на неё можно смотреть под разными углами. Можно воспринимать процессор как конечный автомат, где его состояние определяется значением счётчика программных инструкций и значениями ячеек памяти (т.е. легко заметить, что пространство состояний такого автомата -- огромно). Можно видеть последовательности инструкций как управляющую программу, которая в совокупность с состоянием оперативной памяти образует тот же автомат. Последовательности инструкций это самая низшая форма представления, она сложна для понимания (ввиду огромного числа состояний порождаемого автомата), и лучше её как-то разделять и представлять в виде абстракций более высоких порядков, в идеале программы на языке программирования высокого уровня. Или например иерархической системы маленьких и простых конечных автоматов. Более того, её и генерировать вручную достаточно сложно, именно поэтому и существуют компиляторы языков более высокого уровня. Когда программист уже не знает и не думает о последовательностях инструкций, у него в голове есть сущности более высоких порядков, он задаёт компилятору какие-то правила по выводу одних сущностей из других, и в конечном счёте компилятор генерирует последовательности инструкций. Но важно так же понимать, что управляющая программа может не заканчиваться только на последовательностях инструкций. Это принципиальный момент, многие может упускают из виду. Потому, что как сказано выше, полное состояние автомата так же определяется и оперативной памятью. И одни и те же последовательности инструкций при разном состоянии оперативной памяти могут реализовывать разные функции на более высоком уровне. Я тут на сахаре, когда-то высказывал мысль, мол возможно вредоносное ПО в виде вирусов и для embedded приборов, даже в случае, когда программа записана в однократно программируемую память. Вот это поворот, да? Т.е. не всё определяется последовательностями инструкций в постоянной памяти. В принципе сейчас известны такие техники как "возвратно-ориентированное" программирование (ROP) и более того, применяются на практике. Когда шелл-код невозможно исполнить на стеке, на худой конец на стеке можно разместить некоторый код, который заместит адреса возврата адресами библиотечных функций, выполняющих нужные операции. Не обязательно даже библиотечных функций, нужно просто иметь знать содержимое прошивки, чтоб знать по каким адресам находятся "удобные" последовательности инструкций оканчивающиеся инструкцией ret. Но ROP-код сложно составить, он имеет огромные размеры. Но ведь нет необходимости программировать последовательность инструкций в лоб (о чём мы вообще и говорим!), достаточно дать программисту какой-то язык, способ записать программу, а последовательность инструкций может быть, уже практически буквально, какая угодно. Используя ROP-технику можно записать два десятка базовых слов Форта и реализовать интерпретатор шитого кода. Который получится вполне компактным, а самое главное его уже можно размещать не на стеке, а с в любом месте памяти.
Всё остальное - вкусовщина, предназначенная для дисциплинирования программиста и обеспечения "блочности" кода.
Нет, всё остальное -- это введение сущностей более высокого порядка, позволяющего как раз отдалить программиста от решения задачи в термина потока команд и ассемблера и подвести к решению в терминах более высокоуровневых сущностей, что позволяет в целом упростить, ускорить, удешевить разработку. Очевидный факт, что программирование в терминах ассемблера -- неэффективно, тот же C и или Pascal более эффективны. Но они тоже находятся где-то внизу пирамиды и существует бесконечное множество языков более высокого уровня (это снизу пирамиды под ассемблером лежат конечные автоматы и пирамида кончается). И эти более высокоуровневые языки также более эффективны, как C эффективнее ассемблера. Более того, повторюсь, более высокоуровневые языки позволяют не писать программу в лоб, а создавать программы генерирующие программы, в том или ином виде (в интерпретируемых языках часто есть функция "eval" и программа может проинтерпретировать сгенерированную строку текста, да наконец "интерполяция" строк, где имя другой переменной закодировано в переменной -- типовой трюк, в компилируемых программах есть макропроцессоры способные изменить или сгенерировать текст программы, есть макропроцессоры работающие не на уровне текста, а на уровне понятий языка, как в C++ или lisp). Это не вкусовщина, это способ повысить скорость работы и, главное, овладеть понятиями более высокого уровня, которые на уровне ассемблера становятся недостижимо сложными.
[ZX]