Немного о синтаксисе и безопасности, языков программирования |
1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!
Немного о синтаксисе и безопасности, языков программирования |
volvo |
4.01.2011 11:32
Сообщение
#1
|
Гость |
Итак, Новый Год, заняться особенно нечем, а давайте я вас чуть-чуть "подразню" что-ли? Покажу вам на простых примерах некоторые возможности одного из языков программирования, который многие считают устаревшим. Не вопрос, считайте дальше, на данный момент мы пользуемся Стандартом 2005-го года, т.е., новее, чем у С++, к 2012 готовится очередная версия Стандарта.
Но, собственно, я не собираюсь разжигать здесь холивар, максимум - пробудить интерес. Если кто-то заинтересуется - уже хорошо, если нет - то будем считать, что это все написано, чтоб провести время, не просто так смотря в монитор... Итак. С чего начнем? Наверное, с Hello World? Нет, не интересно. Напишем хоть сколько-нибудь полезную программку. Пускай она получает от пользователя число, и определяет, положительное оно или отрицательное: (Паскаль) var i: integer; (Ада) with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; Что бросается в глаза? "Многословность". Похоже, это - единственный недостаток Ады Давайте теперь немного поговорим о преимуществах. 0. Описание переменных по мере необходимости. (Показать/Скрыть)
1. Циклы For. (Показать/Скрыть)
2. Проверка логических условий. (Показать/Скрыть)
3. Оператор Goto (Показать/Скрыть)
4. Дефолтные параметры процедур/функций. (Показать/Скрыть)
5. Инициализация массивов. (Показать/Скрыть)
6. Еще немного о массивах. (Показать/Скрыть)
7. Параметры подпрограмм. (Показать/Скрыть)
8. Дженерики. (Показать/Скрыть)
Немного о безопасности Недавно мне задали вот такой (очень, казалось бы, простой) вопрос: "Везде, где написано про язык программирования Ада, есть утверждение, что он - более безопасный, чем тот же С/С++. А в чем это выражается?" А давайте попробуем посмотреть в чем это выражается (в основном сравнение происходит с С-подобными языками, Паскаль может не иметь многих из нижеперечисленных недостатков)... 1. Пример программы на С #include <stdio.h>Программа прекрасно компилируется и запускается на выполнение... Но каким будет ее вывод? Вот таким будет вывод: (Показать/Скрыть)
2. Корректен ли следующий код: #include <limits.h>? Несмотря на то, что программа компилируется, здесь присутствуют как минимум 4 серьёзные проблемы. Какие? ... (Показать/Скрыть)
3. Что касается ассоциативности и приоритета операций: Что означает условие if (x & mask == 0) ...? Оно компилируется, но... (Показать/Скрыть)
А вот это: if (x < y < z) ...? И это тоже компилируется, но... (Показать/Скрыть)
4. Еще о синтаксисе... Корректен ли следующий код: // -- Если впереди "зелёный" свет - увеличить скорость? Код компилируется без предупреждений, но... (Показать/Скрыть)
5. Поговорим о перечислениях... enum Alert_Type {LOW, MEDIUM, HIGH, VERY_HIGH};Программа компилируется, но выполняться будет совсем не так, как кажется. В чем дело? А дело в том, что... (Показать/Скрыть)
6. Неопределенности Что здесь происходит: {? А происходит здесь... (Показать/Скрыть)
7. Проблемы с системой типов языка. Программа компилируется, но все равно в ней что-то не так: typedef int Time; Что именно? Уууу... Да здесь целый букет... (Показать/Скрыть)
8. Проблема переполнения. Что произойдет в следующем фрагменте программы на С (или на С++): #include <limits.h> ? ... (Показать/Скрыть)
Disclaimer Только не надо говорить, что примеры-искусственные, и специально подобраны так, что Ада показана выигрышно. Попробуйте привести примеры, как избежать в С/С++ тех неоднозначностей, о которых я написал, чтобы дать возможность компилятору не пропустить ошибку или недочет программиста. По большей части смысл данной темы - в том, чтобы показать, что большинство проблем связано с излишней "гибкостью" языка, в котором "разрешено все то, что не запрещено" (а запрещено явно очень немного вещей), что то же самое и даже гораздо большее можно сделать и без этих правил, разрешающих "всё и вся", с таким строгим синтаксисом, как у Ады. |
Unconnected |
4.01.2011 15:05
Сообщение
#2
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Фухх, осилил) С многим сам сталкивался, вот например кажется такой код в С++
int k; , и это компилировалось, насколько помню.. только непонятно, в чем заключалось условие, в успешном присваивании? С условиями жизненно, помню, ловил такое долго) Правда, можно сделать if U1 then if U2 then ... , тогда точно будут по отдельности выполняться. А вот такую штуку
было бы неплохо в паскале завести, давно хочу) Ну, я так понял, что во многом Ада даёт "защиту от дурака", и если не выделываться (ну типа if (a<b<c) - тут на ходу дотумкать можно, что компилятор может не понять правильно), то скорее всего всё будет хорошо. Ну и где надо она гибше, да.. с всеуничтожающим break хорошо придумали. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
4.01.2011 19:47
Сообщение
#3
|
Гость |
Цитата и если не выделываться (ну типа if (a<b<c) - тут на ходу дотумкать можно, что компилятор может не понять правильно), то скорее всего всё будет хорошо Ну вот и приведи мне решение (хочешь - на Паскале, хочешь - на Сях, хочешь - на С++), которое позволит мне на этапе компиляции забраковать неправильные варианты вызова процедур/функций (я про пункт "7. Проблемы с системой типов языка") Цитата я так понял, что во многом Ада даёт "защиту от дурака" Это не совсем "защита от дурака". Это надежность программ прежде всего. Кстати, очень многие вещи остались "за кадром": встроенная в язык работа с подзадачами/потоками (с 1983 года !!! Причем средствами языка, нет никакой зависимости ни от ОС, ни от используемого компилятора) и межпоточное взаимодействие (аналогично, средствами языка), и защищенные типы (попробуй написать потокобезопасный контейнер на Паскале, например, чтоб с ним можно было безопасно работать из десятка потоков)... И так пост большой получился... Если кому интересно - расскажу. |
-TarasBer- |
4.01.2011 20:09
Сообщение
#4
|
Гость |
> Что бросается в глаза? "Многословность".
Насколько я знаю, для закрытия блока надо тоже его назвать. По-моему, это очень сильно избавляет от поиска пропущенного енда (вызывающиего ошибку компиляции под конец модуля) по всему коду, то есть плюс. > Описание переменных по мере необходимости. Это прикольно, но процедуры на более чем 100 строк считаются дурным тоном. А для коротких процедур завести переменную в начале не обломно. > Циклы For. + > Проверка логических условий. Все уже сто лет привыкли, что полной проверки нет и пользуются этим. На крайняк можно написать if a then if b... > Оператор Goto + > Дефолтные параметры процедур/функций. + > Инициализация массивов. + > Еще немного о массивах. > (чем не "сборка мусора"?) Надеюсь, там не сборка, а детерминированное удаление при выходе из зоны видимости? Другой автоматизации работы с памятью я не признаю. > Параметры подпрограмм. Не вкурил. Есть же директива const. > Дженерики. То есть можно делать приколы из С++, в котором шаблоны - функциональный язык, выполняющийся во время компиляции? Это интересно. > Системы счисления + > Смешивание "=" и "==". За это надо построить машину времени, вернуться в прошлое и убить Ритчи. И эта зараза во всех новых языках!!! > Поговорим о перечислениях... А что, перечисления Си даже в отладчике видны как числа? Я так не смогу, я привык, что в отладчике вижу нормальные имена. > гибкие селекторы - можно сделать и так: Да, тут у Си полный облом. > Ошибка компиляции: несоответствие типов параметров Это правильно, но принудительной ретипизацией это можно обойти? > В Аде каждый раз, когда происходит переполнение выбрасывается исключение (на всех поддерживаемых платформах). То же смое касается и попытки деления на 0, и выхода за пределы массива, ну, и так далее... Не понял, в код вставляются проверки выхода за диапазон? Это отрубаемо, надеюсь? > только непонятно, в чем заключалось условие, в успешном присваивании? Нет. В том, что результат присваивания не ноль. > var a:integer; > m:array [1..a] of byte; И как ты это себе представляешь? Не, ну если массив идёт в самом конце описания, то это ещё можно сделать теоретически. А если нет? То что делать с участком памяти, идущим за массивом, когда массив захотелось удлинить? |
-TarasBer- |
4.01.2011 20:17
Сообщение
#5
|
Гость |
А вот что меня напрягает в синтаксисе Паскаля (и у Ады тоже, кажется, есть этот минус), так это то, что функции, не принимающие параметров, можно записывать без пустых скобочек.
Где-то была тема, в которой три человека очень долго думали, что в данном контексте значила pointer(a) - вызов метода или указатель на метод? Нужен был указатель, но почему он не вызовется, сказать наверняка было невозможно. Да и вообще, это нарушает логичность. |
volvo |
4.01.2011 20:43
Сообщение
#6
|
Гость |
Цитата Насколько я знаю, для закрытия блока надо тоже его назвать. Это настраиваемо. Мой компилятор с этим справляется сам, посему у меня отключено. А вообще - да, окончательную проверку на Styling программа не пройдет, пока все отступы не будут выровнены, все блоки не будут названы, и все подпрограммы не будут размещены в алфавитном порядке с предварительным описанием в файле спецификаций (некий аналог Interface-части юнитов Паскаля. Кстати, по той же причине - облегчение поиска в случае необходимости).Цитата А для коротких процедур завести переменную в начале не обломно. Ниже я написал один из способов применения. Это удобно...Цитата Все уже сто лет привыкли, что полной проверки нет и пользуются этим. А если мне НАДО полную проверку? Ада-решение: вместо "and then" пишется просто "and", вместо "or else" - просто "or"... Паскаль заставляет меня опять заморачиваться с директивами компиляции, остальные языки - тоже...Цитата Надеюсь, там не сборка, а детерминированное удаление при выходе из зоны видимости? Другой автоматизации работы с памятью я не признаю. Я тоже не терплю языков, которые навязывают мне свой GC. По этой причине я не стал изучать ничего из .NET-а, по этой же причине не ушел на Оберон... Там именно удаление при выходе из области видимости... Сборшик мусора Стандартом Ады не запрещен, но и не навязывается. Есть - используй, нет - не используй...Цитата А что, перечисления Си даже в отладчике видны как числа? Отладчик добавляет к числу еще и идентификатор. Но все равно, неявное приведение к типу int делает свое черное дело при работе программы...Цитата Не понял, в код вставляются проверки выхода за диапазон? Это отрубаемо, надеюсь? Да, для этого надо пересобрать программу с другими ключами.Добавлено через 9 мин. Цитата Нужен был указатель, но почему он не вызовется, сказать наверняка было невозможно. У Ады совершенно нет этой проблемы (по крайней мере, попадать в такое положение, при котором возникала бы неоднозначность мне не приходилось). Если нужен указатель на метод - P'Access, нужен вызов метода - просто P... В Паскале - помню, было... А пустые скобки меня в Дельфи/FPC напрягают, например. |
TarasBer |
4.01.2011 22:22
Сообщение
#7
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Ниже я написал один из способов применения. Это удобно...
С одной стороны, удобно, с другой, не бьёт по рукам любителей простыней. > А если мне НАДО полную проверку? Зачем? Ради побочных эффектов вычисления операндов? Тогда заранее в отдельные переменные записываешь результаты вычислений операндов. По-моему это не так часто происходит, чтобы заводить отдельно оператор "и-с-полной-проверкой" и оператор "и-с-неполной-проверкой". По крайней мере я ни разу не ощутил потребность в таком операторе. > Там именно удаление при выходе из области видимости... И можно создавать свои объекты, которые в автовызываемом деструкторе делают освобождения ресурсов, закрытия файлов итд? А ГЦ недетерминирован, ставит крест на приложениях реального времени, всё равно в кривых руках память течёт (да), а в прямых, если в языке есть автовызов деструктора, нафиг он нужен? Стандартный счётчик ссылок не работает только в хитрых структурах, двусвязных списках, например, ну так для них объектную оболочку можно сделать, чтобы все опасные операции внутри реализации класса были зашиты, а оболочка это сама всё вычистит при выходе из зоны видимости. > Да, для этого надо пересобрать программу с другими ключами. Тогда нормально. Хошь - компилируй в программу с полным контролем и безопасностью, хошь - на скорость дави. > У Ады совершенно нет этой проблемы Ну надеюсь. Просто пустые скобки - это как сигнал, что типа это может иметь побочные эффеты, если что, надо кешировать. А в Дельфи я нашёл эту тему с неоднозначностью: http://www.gamedev.ru/code/forum/?id=141396 -------------------- |
volvo |
4.01.2011 23:29
Сообщение
#8
|
Гость |
Цитата И можно создавать свои объекты, которые в автовызываемом деструкторе делают освобождения ресурсов, закрытия файлов итд? Угу. -- В отдельном пакете описываем объект: Для Controlled-типов процедуры Initialize и Finalize (конструктор/деструктор, можно и так) вызываются автоматически. Все, что мне останется сделать: declare Если же мне захочется самому вызывать конструктор/деструктор - не надо наследоваться от Controlled... |
TarasBer |
5.01.2011 0:03
Сообщение
#9
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Для Controlled-типов процедуры Initialize и Finalize (конструктор/деструктор, можно и так) вызываются автоматически.
Всё, хочу перейти на Аду. Есть какие-нибудь бесплатные среды под Вин32? Мне достаточно редактора кода и заголовков от ВинАПИ, формошлёпалку не надо. Добавлено через 9 мин. А, я что ещё вспомнил. Могут ли out-параметры быть по умолчанию? Мне не удалось в Дельфи написать var s: string = nil^, пришлось вспомнить, что передача по ссылке - это неявная передача указателя и написать s: PString = nil. -------------------- |
volvo |
5.01.2011 0:16
Сообщение
#10
|
Гость |
Цитата Есть какие-нибудь бесплатные среды под Вин32? Есть. Без формошлепалки, IDE для Win/Lin со всеми необходимыми пакетами можно взять здесь (просто выбираешь Free sortware or Academic Development, можешь даже не указывать мыло, и собираешь для себя пакет скачки. Обязательно качать Gnat GPL и Win32Ada, это как раз то, что ты описал - заголовки WinAPI и компилятор со всеми прибамбасами. Я для себя еще брал QtAda, но это - для любителя особых извращений...)Добавлено через 8 мин. Цитата Могут ли out-параметры быть по умолчанию? Нет, только In-параметры. Даже In Out не могут. А оно надо? |
TarasBer |
5.01.2011 0:28
Сообщение
#11
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Нет, только In-параметры. Даже In Out не могут. А оно надо?
Ну мне как-то понадобилось, чтобы функция когда надо - возвращала значение в некий параметр, а когда не надо - не возвращала, ну то есть иногда он мне не интересен, а заводить спец переменную ради возвращения того, что мне не надо, некрасиво. Пришлось извращаться через передачу указателя. -------------------- |
volvo |
5.01.2011 1:20
Сообщение
#12
|
Гость |
Цитата а заводить спец переменную ради возвращения того, что мне не надо, некрасиво. Я посмотрю, что ты скажешь, когда Ада заставит тебя вместо ReleaseDC (hwnd, My_DC); написать i_Result : Win32.INT; Все Сиш-ные и Дельфийские замашки, основанные на хаках и бесконтрольном приведении типов придется забыть. Ибо Ада тебе даже не гарантирует, что матрица хранится по строкам. Она может храниться и по столбцам, как в Фортране... |
Lapp |
5.01.2011 13:20
Сообщение
#13
|
Уникум Группа: Модераторы Сообщений: 6 823 Пол: Мужской Реальное имя: Лопáрь (Андрей) Репутация: 159 |
volvo, спасибо за это эссе, +1
Я встряну мимоходом. А если мне НАДО полную проверку? Ада-решение: вместо "and then" пишется просто "and", вместо "or else" - просто "or"... Паскаль заставляет меня опять заморачиваться с директивами компиляции, остальные языки - тоже... Я уже как-то говорил об этом.. За всю свою практику я не встретил ни одного случая, где это было "НАДО". Все примеры на эту тему как правило сродни чесанию правой пяткой за левым ухом. Так что я для себя сейчас считаю, что если мне это вдруг "НАДО" - значит, что-то не так )). Логика - штука хитрая. Красота выражения говорит о его правильности обычно. Так что лично я не буду возражать, если мне однажды все-таки придется "заморочиться с директивами".. Фухх, осилил) С многим сам сталкивался, вот например кажется такой код в С++ А вот это как раз очень жизненно. С одной стороны, этой ошибке подвержены практически все, кто переходит с Паскаля на Си. А с другой,int k;, и это компилировалось, насколько помню.. Цитата только непонятно, в чем заключалось условие, в успешном присваивании? - такая конструкция очень удобна и часто применяется. Значит она следующее: присваиваем k некоторое значение (конечно, там стоит обычно выражение из переменных или функций), и если оно ненулевое, то..Забавно, что паскалисту (я говорю про начинающих, а не зрелых, которые осознают потребность такого даже в Паскале) такая конструкция совершенно чужда, он просто не мыслит в таких категориях )). Offtop: Это сообщение не увидело бы свет, если бы FF после крэша машины (блин, это меня уже напрягает, надо что-то делать) не восстановил практически полный его текст. За что ему спасибо! подправил, была опечатка.. Сообщение отредактировано: Lapp - 5.01.2011 15:28 -------------------- я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой |
TarasBer |
5.01.2011 15:29
Сообщение
#14
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Все Сиш-ные и Дельфийские замашки, основанные на хаках и бесконтрольном приведении типов придется забыть.
Э, а как же прямая отрисовка в буфер? У меня есть только указатель на начало пиксельного блока, ширина и высота картинки. Вся отрисовка держится на бесконтрольной ретипизации. > Забавно, что паскалисту (я говорю про начинающих, а не зрелых, которые осознают потребность такого даже в Паскале) такая конструкция совершенно чужда, он просто не мыслит в таких категориях )). А такая?
-------------------- |
TarasBer |
5.01.2011 15:59
Сообщение
#15
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> for i in 1 .. 10 loop -- i вообще не описывается
А если написать так? for i in 1 .. L.Count - 1 loop то, надеюсь, будет использован знаковый тип? Вспомнился прикол, как некоторые брали word и материли "глючную дельфу", которая почему-то для пустого списка пыталась перебирать индексы от 0 до 65535. -------------------- |
volvo |
5.01.2011 17:08
Сообщение
#16
|
Гость |
Цитата Вся отрисовка держится на бесконтрольной ретипизации. Для крайних случаев (когда без этого уже совсем никак не обойтись) есть модуль Ada.Unchecked_Conversion, который позволяет привести любой тип к любому другому. Но слишком часто прибегать к его услугам (в смысле строить программу так, чтобы были сплошные преобразования типов, потому что "я сам знаю, как мне делать, почему меня компилятор ограничивает?") - это моветон.Цитата А если написать так? for i in 1 .. L.Count - 1 loop то, надеюсь, будет использован знаковый тип? Еще сомневаешься? |
TarasBer |
5.01.2011 20:24
Сообщение
#17
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Я посмотрю, что ты скажешь, когда Ада заставит тебя вместо
Мда, я представил для SendMessage... Ну для самый частых функций ещё обёртку можно сделать, проглатывающую возвращаемое значение. Кстати, инлайн-функции там есть? > Но слишком часто прибегать к его услугам (в смысле строить программу так, чтобы были сплошные преобразования типов, потому что "я сам знаю, как мне делать, почему меня компилятор ограничивает?") - это моветон. А мне, кроме графического модуля, нигде и не надо. В Д7 я ещё делал наглые преобразования к типу, с которым работает некоторая структура, но это от отсутствия генериков. > Еще сомневаешься? Тогда нормально. А вместо диапазона писать название перечислимого типа можно? for i in TMyType do... А то так запарило в одном месте для 3 разных типов писать
Что ещё не хватало в Дельфи. А, контроль вариантных полей во время выполнения (во время компиляции, увы, никак).
-------------------- |
volvo |
5.01.2011 21:29
Сообщение
#18
|
Гость |
Цитата А вместо диапазона писать название перечислимого типа можно? Легко... Будет перебираться весь тип, от самого первого до самого последнего значения, и всего делов. Обрати внимание, для того чтобы напечатать идентификатор элемента, достаточно сделать MyType'Image. Это тоже встроено в язык, не нужны никакие Дельфийские шаманства с RTTI. Цитата А, контроль вариантных полей во время выполнения (во время компиляции, увы, никак). Увы - это ты про Дельфи? Вот это что-ли? (правда тут у тебя небольшой облом - селектор должен задаваться один раз, при инициализации переменной. Менять его ты не имеешь права. Задавать переменную без селектора - тоже). Но как доп. средство для контроля - пойдет. |
TarasBer |
5.01.2011 21:51
Сообщение
#19
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Обрати внимание, для того чтобы напечатать идентификатор элемента, достаточно сделать MyType'Image.
Да, такую фичу я тоже хотел (типа чтобы Str(mt, S) писало в S имя mt), но так, в качестве баловства, серьёзного применения ей пока не вижу. Image - это функция, возвращающая строку? > правда тут у тебя небольшой облом - селектор должен задаваться один раз, при инициализации переменной Это я на стадии компиляции должен указывать значение селектора? Тогда что вообще дают такие вариантные записи? Или всё это не обязательно? -------------------- |
volvo |
5.01.2011 22:47
Сообщение
#20
|
Гость |
Ну, максимум что можно предложить - это описать запись как "нелимитированную", то есть дать селектору значение по умолчанию, что позволит описывать экземпляр структуры без начального значения селектора, и, следовательно, разрешит менять селектор в рантайме. Только менять его можно будет только вот таким образом:
(то есть, в агрегате должны присутствовать все поля, связанные с данным селектором. Как видишь, это очень просто делается. А потом - уже меняй любое нужное тебе значение. Если то, что ты меняешь недоступно при установленном в настоящий момент селекторе, вылетит CONSTRAINT_ERROR). |
Текстовая версия | 5.10.2024 0:12 |