Comments 112
За индексы, начинающиеся с 0 вместо 1, будет гореть в аду!
Я понимаю, что у такого подхода есть минусы. Но ведь есть и плюсы. Поэтому такой радикальности ведь не надо. В разных странах есть например и этажи с номером 0 и ничего - живут ведь люди.
Но вот индексация с нуля — это не недостаток, а вполне нормальная возможность. Пишу на С/С++ уже 20 лет и никаких проблем с этим не испытывал, даже на первом курсе института когда только начинал учить Си:)
Да и фоннеймановская архитектура здесь не при чем. Есть микроконтроллеры, основанные на гарвардской архитектуре, и под них все равно пишут на Си.
Да, я НЕ считаю недостатками небезопасную работу с указателями, отсутствие сборки мусора, индексы не с нуля, отсутствие проверок выхода за границы массива, не экстремально строгую типизацию как в Rust и т.п. Это все особенности низкоуровневого языка, без которых язык был бы другим. Но это не отменяет того факта, что во время создания Си многие подходы и парадигмы были неотработаны (да и вообще программированием занималось значительно меньше людей чем сейчас), поэтому в дизайне языка разумеется существуют некоторые ошибки.
особенности низкоуровневого языка
Ирония — когда С создавался, его звали "ЯВУ", сейчас "понизили уровень", я в каком-то месте нарывался на определение С как "ассемблер высокого уровня". А то, что сейчас ЯВУ, в те времена просто не могло быть воображено (даже Python, и тот ещё не мог поместиться в тогдашние парадигмы ИМХО).
Lisp -1958 г., Simula — 1967 г. Можно и другие поискать и найти.
Алгол успел появиться, пройти глубокое обновление, после него — Паскаль уже успел появиться. И всё — до Си.
Си — язык среднего уровня. Затем и нужен.
имя массива это адрес первого элемента, а не объект
Как минимум, если завернуть массив в структуру, можно будет его передавать в/из функции и даже пользоваться простым присваиванием.
В чужой монастырь со своим уставом не ходят. Пишите на паскале, там хоть с -100 или с true можно начинать массив.
ПХП делает вид что не слышит того, что вы говорите
А ещё можно применить карты
А вот чтоб не абстрактно можно написать, а ночью разбуди, любой программист, претендующий на C++, знал, где такое готовое взять?
Где взять ограниченные диапазоном числа и перечисления. Где массив взять, который с ними скомбинируется и позволит использовать такой параметр как индекс, как в обычных языках
Индексация с единицы тоже способна приводить к багам.
Скажем, любые алгоритмы длинной арифметики просто просят индексацию с нуля.
Да начнётся священная война!
0 — это не совсем индекс, а скорее смещение от начала массива. Поэтому у первого элемента индекс 0. Более того, постфиксный оператор []
это синтаксический сахар для *
(разыменование указателя). Т.е. <pointer> [ <expression ]
то же самое, что и *( <pointer> + <expression> )
.
Хотите детские индексы с 1 — пишите на basic.
И 2МГц, и 12МГц, и 33МГц. Перестало быть актуальным на персональных компьютерах где-то в эпоху Пентиумов. А на бесчисленном множестве контроллеров актуально до сих пор.
Но в итоге это стало больших рассадников багов(не забыть писать Count-1 и т.п.) и потерь человеческого времени, т.к. человеку привычнее считать с 1
Хм. Насколько я знаю, человек привыкает считать массивы с 0 где-то ко второму месяцу обучения программированию :) Кроме того, контроль границ массивов в языки пришёл ещё в 1980-е, а чуть позже и циклы foreach. Так что проблема явно надумана.
Всё же стоит признать, что на C программировать практически никто не умеет. Стоит открыть какую-нибудь cve.mitre.org и поизучать уязвимости, процентов 90, если не больше там будут уязвимости, напрямую связанные с языком, его особенностями, реализацией и возможностью как выстрелить себе в ногу, так и отстрелить её.
К примеру, будь это все написано на каком-нибудь Pascal, этих уязвимостей бы просто не существовало. Все считают, что они умеют писать на C и это дает им какие-то преимущества, на деле же писать на нём грамотно и без ошибок умеют единицы. При это именно программировать, то есть составлять алгоритмы работы, умеют очень многие и очень хорошо. А вот реализовывать их на C почти никто не умеет. Но при этом постоянно лезут это делать.
Почему, кстати, программировать до сих пор учат на паскале, а не на C или C++ или Python, очень хорошо раскрыто в первом томе книги Столярова, рекомендую (https://habr.com/ru/news/t/545142/)
Всё же стоит признать, что на C программировать практически никто не умеет. Стоит открыть какую-нибудь cve.mitre.org и поизучать уязвимости, процентов 90, если не больше там будут уязвимости, напрямую связанные с языком, его особенностями, реализацией и возможностью как выстрелить себе в ногу, так и отстрелить её.
Всё же стоит признать, что от замены C на любой другой язык программирования в вашей цитате, ничего не меняется. Фраза однозначно верна для любого языка.
Серьезно? И как же вы сделаете buffer overflow или нарушение boundary на Pascal/Java/Python/Go/Perl/whatever?
P.S. Ну на каком-нибудь Паскале можно еще, если специально прямо постараться, там указатели есть. Но в целом все эти проблемы уходят как класс. Каждый второй cve - buffer overflow и RCE при парсинге ввода данных в стиле "забыл -1 написать в конце" или "выделил памяти меньше чем мне прислали данных".
Серьезно? И как же вы сделаете buffer overflow или нарушение boundary на Pascal/Java/Python/Go/Perl/whatever?
Во-первых, если я правильно понимаю, то в данном контексте речь все ж о плюсах, а не о С. Все ж Java - это совсем не уровень С. Далее.. У плюсов хватает недостатков именно дизайна, типа инклудов. Касаемо всего остального, у меня сложилось мнение, что по большей части проблемы от непонимания, как работает та или иная фича (недавно коллега, который лучше меня знает плюсы, показал мне очередную "проблему безопасности" при использовании ссылок на элемент вектора, на деле оказавшуюся просто особенностью использования памяти типа массива, а не списка.
И таких примеров полно. Я помню как в универе офигевал от того, что вечно получаю какие-то ошибки при работе со строками. Но проблема была лишь во мне, поскольку я для себя решил учиться программить на плюсах, параллельно программу сдавая на паскале. Ну и оказался просто не готов к возможности прямого доступа к памяти
Второе. Есть мнение очень распространенное, что сегодня быть программистом намного легче, чем во времена перфокарт и т.п. Типа тогда были монстры просто, а сегодня достаточно простых вчерашних студяг и питона с его кучей либ. На самом деле просто разросся рынок, резко пошли вверх объемы ПО, и по большей части это ПО живет недолго: то конкуренты обгонят, то состарится. Конкуренция бешеная, за качеством софта следят не особо. И во всей этой кутерьме, да, программистом, который пишет коммерческий софт быть несложно. Беда в том, что быть ХОРОШИМ программистом все так же непросто, как и раньше. Потому такой разброс ЗП и качество софта. И потому хороший сишник - это не вчерашний студент. Как и хороший джавист и дельфист и т.п. Хороший проггер отсечет 99% всех потенциальных "выстрелов". А посредственный и на джаве напишет код, который будет медленным, и который придется не просто рефакторить на скорость, а вообще переписывать архитектурно.
Всё же стоит признать, что на C программировать практически никто не умеет. Стоит открыть какую-нибудь cve.mitre.org и поизучать уязвимости, процентов 90, если не больше там будут уязвимости, напрямую связанные с языком, его особенностями, реализацией и возможностью как выстрелить себе в ногу, так и отстрелить её.
Но багов из-за индексации с нуля там будет раз-два и обчёлся.
Крайне удивляет утверждение, что "программировать до сих пор учат на паскале ". Это, простите, где? Из известных мне примеров: C, C++, Python, Java.
Зачем писать Count-1 ??? Если мне надо пройти 10 элементов массива то:
for(uint8_t i = 0; i < 10; i++) {...}
А если бы начиналось с 1, то пришлось бы писать 10 + 1. Т.е. сейчас мне не надо писать count-1, а пришлось бы писать count+1 если бы всё было так как вы предлагаете.
Не обязательно, если включить десять посредством i <= 10
то можно начинать от 1 :)
Но проблема раздута сверх всякой меры. В школе много лет программировал на бейсике, а когда перешёл на C, нижняя граница массива от 0 стала просто аксиомой.
А главное, что были введены { } вместо begin-end, next, then
операция <= чуть медленнее <
O_O
С какой это стати?
потому что это "меньше", а затем "равно". два шага вместо одного.
Тоже встречалось такое утверждение, объясняли тем, что "меньше равно" разбивается на операции "меньше или равно". Разнообразие ассемблерных условных переходов мягко намекает, что это не так.
Полно языков с индексами по-умолчанию как с нуля, так и с единицы. Если по какой-то причине для вас это важно, выбирайте язык с учётом этого критерия.
Например, с нуля C(,++,#), Python; с единицы Fortran, Matlab, R, Julia. Я писал и на тех и на тех, в том числе почти одновременно, особых проблем не увидел.
Начинать индексы с нуля - более математично. Например:
1) array[i%count]
2) индекс - количество элементов перед текущим
Мое ИМХО - индексы с нуля позволяют сократить количество +1 -1 в коде.
Си и его предки суть улучшенный ассемблер. Сделали по тупому. Во многом из-за простого и быстрого способа обнуления регистров.
На уровне компилятора и определения циклов можно поправить. Но создателям было пох, ибо всё равно лучше асма, а остальные — привыкли.
Ряд натуральных (то бишь естественных) чисел намекает что вот нихера.
Как насчёт международного стандарта ISO 80000-2 «Mathematical signs and symbols to be used in the natural sciences and technology»?
![](https://habrastorage.org/webt/yq/xf/pb/yqxfpb7efklx1zpz_-uypwbzv_y.png)
Ой вы не правы про ряд натуральных чисел.
Без нуля он неполон и убог.
Я продолжу:
3) array[i*N+j]
Справедливости ради, он и с нулем не кольцо.
Потому, что нет обратных по операции +.
Вот целые числа - это кольца, да.
Однако, без нуля теряется красота.
Рассмотрим полный набор остатков по модулю N.
Можно брать {0,...,N-1} или {1,...,N}.
Это множество - группа с операцией "сложение по модулю".
В первом случае нейтральный элемент вегда 0, независимо от N.
Во втором случае нейтральный элемент - N, у каждой группы свой.
Теряется красота.
Уточнение: без 0 ряд натуральных чисел даже перестаёт быть полукольцом
По опыту работы с своим и чужим кодом в языках где индексы начинаются с 0 и 1 — ошибки на 1 совершаются вне зависимости от языка, обобщённого решения этой проблемы нет, помогают итераторы по диапазонам, но всё равно рано или поздно будет индексация и ошибки. Проблема не в индексации которая "неправильная", а в людях которые делают ошибки.
Почему 20хх годы — 21-й век? Потому что какой-то дебил придумал нумерацию с единицы.
И ты не можешь просто разделить или умножить чтобы что-нибудь отмасштабировать, надо сначала вычесть 1, потом добавить. или сначала добавить потом вычесть? да хрен его знает. Ужасно бесит. Работал одно время со сраным матлабом — я не знаю как монитор выжил!
Си и Ассемблер — пара языков, единственные позволяющие создавать качественные программы. Ничего существенно лучше нет и не предвидится. Радует что ныне всё больше людей начинают осознавать куда катится софт и начинают вспоминать про Си.
Ничего существенно лучше нет и не предвидится
Эта фраза выдаёт в вас просто фантастическую нехватку кругозора. За всю историю существования человечество успело наклепать несколько тысяч языков программирования. Вы действительно хотя бы кратко ознакомились хотя бы с процентом от этого количества, чтобы иметь основание для подобного утверждения?
А не надо путать индексацию с нумерацией.
Почему 20хх годы — 21-й век?
20хх годы - 21 век. Номер века - это не первые цифры года. Это именно его порядковый номер. А первый век новой эры был именно что 1-100 годы.
Согласно смыслу количественных числительных, когда у вас появляется первый седой волос - это таки один седой волос, второй - это когда к первому добавляется еще один, т.е. два.
Нулевой - это другое. Это когда у вас еще ничего нет, т.е. ноль. Потому нулевой километр - это начало. Точка. Первый километр пошел, когда что-то уже проехали.
А при индексации можно вообще с любого числа начинать, и даже не подряд (другой вопрос, что не каждый язык программирования такое позволит для массивов). Как нарисуем индексы для элементов, так и будет.
Если же выбора нет, и есть только один вариант, то для индексации массива удобнее таки начинать с нуля, поскольку адрес нулевого элемента указует на начало массива, т.е. еще самое начало, и ни одного элемента еще не прошли. Адрес начала второго элемента указывает на конец первого, т.е первый элемент прошли, второй еще нет (второй палец для счета загибать еще рано).
Опять же, смещение от начала массива у первого элемента - ноль. Тоже удобно плясать при индексации.
Так что x[0] в сях - это не нулевой элемент массива, а таки первый, но в то же время он же - элемент с нулевым индексом.
@tyomitch
Я жил в доме, где нумерация этажей начиналась с -2, и теперь требую ЯП с индексацией массивов с -2!
Опять же, не надо путать индексацию с нумерацией.
Впрочем, любой язык с произвольной индексацией массивов вам в помощь. MUMPS, например.
Хотя в вашем случае и Паскаль справится:
var a:array [-2..MAX_FLOOR] of TFloor;
А это не индекс, а сдвиг (offset) от начала блока памяти на sizeof его элемента
К старту курса по C++ выпустили статью по истории языка C. Многое говорит, мне кажется.
Первый компилятор С++, просто транслировал С++ в С. Шаблоны могут быть обработаны препроцессором и легко транслироваться в С. Т.к. С содержит указатели на функции, то таблица виртуальных функций можно сделать как структуру, указатель на которую будет лежать в начале простой структуры. Win API это делает прямо за счет макросов когда в С++ это классы, а в С это структуры с указателями функций.
это в каком месте язык C безопасный?
А бывают ли безопасные?
За пределами стэка и строк, поэтому стремится туда выбраться.
Можно безопасно получать segmentation fault в большом количестве :) А если серьёзно, тоже несколько напрягла эта фраза. Возможностей ступить в лужу с C невероятно много, я всё же считаю его достаточно низкоуровневым.
Однако сам язык полезен, он даёт базу программистам, указатели, работа с памятью. Становится понятно, как устроены вещи под капотом более высокоуровневых языков.
Я для себя, например, нашёл язык полезным для написания платформозависимых API для своей .NET библиотеки. Ошибок с памятью получил уже достаточно :)
Однако сам язык полезен, он даёт базу программистам, указатели, работа с памятью. Становится понятно, как устроены вещи под капотом более высокоуровневых языков.
Вот это ключевой момент.
Знание (хотя бы на базовом уровне) С и понимание принципов писания на нем (пусть это еще не умение на нем писать, приходящее с опытом) делает из мартышки, которую на ускоренных курсах научили собирать из готовых кубиков нечто как-то работающее, более-менее разумного разработчика.
Согласен с небезопасностью данного языка в общем смысле, но давайте посмотрим на контекст - есть несколько важных обстоятельств, которые делают его безопаснее ассемблера с одной стороны и условного C++ с другой.
1 (оно же главное преимущество перед ассемблером). Возможность структурированного программирования. Конечно, спагетти-код, состоящий из условных и безусловных переходов, в Си допустим, но в конечном счёте стал моветоном (и это прекрасно).
И в этом плане Си однозначно намного безопаснее ассемблера.
2. (оно же главное преимущество перед C++ в применении к низкоуровневому программированию) - это низкоуровневая конкретность. Например, не предоставляется никаких контейнеров "из коробки", а почти всё "сложное" поведение (например, управление памятью) вполне гармонирует с поведением Unix или вовсе явно вынесено в библиотеки операционных систем (напр., библиотеки POSIX). А поскольку наследие Unix сейчас в том или ином виде проникло буквально во все распространенные операционные системы (включая не Unix-подобные, вроде той же MS Windows), то и Си на них гармоничен.
Как писал разработчик тех же языков Паскаль, Модула и Оберон, т.е. эксперт в безопасных языках (и кстати видный критик классических C-подобных языков) Никлаус Вирт: "язык программирования, операционная система и аппаратное обеспечение образуют единую платформу, а потому проектироваться в идеале также должны как единое целое".
"Преимущество" №2 совершенно непригодно при высокоуровневом программировании, но а) позволяет намного быстрее портировать язык Си на любые платформы, б) позволяет "локализовать" "проблемное" поведение в "типичных проблемных местах" - в то время как C++ проблема может возникнуть "откуда не ждали", спонтанно появляться и пропадать, вызывать совершенно неожиданные последствия, и т.д. (как говорится, "выстрелить в ногу на Си проще, чем на C++, но если вам удастся это сделать на C++, вы отстрелите себе намного больше").
К сожалению, мы не знаем, как выглядел бы мир, где Unix (а за ним и C, а за ним и все имеющиеся промышленные языки программирования) не поднялся; а было бы интересно посмотреть, как выглядит мир IT, где язык ассемблера был "побежден" не C, а, скажем, конкатенативным языком Forth. Но связка Unix/C крепко дала корни, а следовательно в любых производных вычислительных системах найдётся ниша, в которой C окажется уместен.
А поскольку наследие Unix сейчас в том или ином виде проникло буквально во все распространенные операционные системы (включая не Unix-подобные, вроде той же MS Windows), то и Си на них гармоничен.
А что, на винде уже можно писать на C без костылей типа MinGW/Cygwin?
б) позволяет "локализовать" "проблемное" поведение в "типичных проблемных местах" — в то время как C++ проблема может возникнуть "откуда не ждали", спонтанно появляться и пропадать, вызывать совершенно неожиданные последствия, и т.д. (как говорится, "выстрелить в ногу на Си проще, чем на C++, но если вам удастся это сделать на C++, вы отстрелите себе намного больше").
Отнюдь. Список UB в C включает в себя нарушение инвариантов, которые являются глобальным свойством программы.
Наличие контейнеров из коробки в плюсах не заставляет вас ими пользоваться. Это ж не Go без дженериков, можно написать свои.
Лично меня не заставляет, а вот про условных коллег из другого отдела я так сказать точно не могу.
Более того, в С из коробки есть, например, сортировки, зачатки парсинга, зачатки работы со строками, и так далее. Довольно странно апеллировать именно к контейнерам.
Все перечисленные функции реализуются в модели типов языка C, а не являются особо специфицируемой надстройкой над ними. И парсинг, и сортировки, и что угодно ещё - это просто определенные действия, совершаемые при помощи указателей на области памяти (на функции или данные), а не абстракция, которая может быть реализована разработчиками компиляторов, строго говоря, практически как угодно.
А, к слову о низкоуровневой конкретности, наличие темплейтов позволяет писать код так, что компилятору куда проще его оптимизировать. Массив из 5-10 элементов на плюсах сортируется раз в 40 быстрее, чем на С, просто за счёт отсутствия оверхеда из-за непрозрачного
void*
.
Тем не менее посмею заметить, что погоня за производительностью за счёт усложнения системы - не лучший путь. Как правило, системные программы должны работать не как можно быстрее, а в срок выполнять каждую задачу (ведь это требование к системе реального времени, а связка ОС+драйвера является как минимум системой мягкого реалтайма).
А усложнение системы во имя ускорения... похожим путём уже ходили CISC-процессоры, и в итоге пришли к системе микрокоманд (практически RISC-внутри-CISC).
Предположу (возможно, ошибусь), что идеальным для компиляторов было бы не "уход вверх", в "высокий уровень", а наоборот, написание программ командами сразу под какую-нибудь виртуальную машину, такую как JVM, LLVM или например Форт-машина. При этом почему-то так мало кто делал (возможно конечно, что по исключительно историческим причинам), и в том числе поэтому сейчас мы получаем LLVM-компиляторы классических языков программирования, где изначально ничего такого не задумывалось ни сном ни духом.
модули не в состоянии экспортировать столько всего полезного, сколько заголовочные файлы. Ведь у С есть ещё язык макросов, чего точно нет у языков с модулями.
P.S. В чужой язык с уставом своего не ходят!
Предоставьте в студию модульную систему, позволяющую построить систему, к примеру, как вокруг 16 битного int, так и вокруг 32 битного... Что ни говори, а именно лексические макросы C дали ему такую популярность...
Вообще, говорить, что автор CPL изобрел один из самых популярных языков программирования, это все равно что говорить, что Ньютон изобрел атомную бомбу. Конечно, цепочка исследований от его работ до создания атомной бомбы прослеживается. Но в CPL нет вообще ничего общего с С, кроме разве что того факта, что они оба императивные.
Примечательно, что разработчики добавили в язык структуры — тогда их не было ни в одном языкеОшибка. Гетерогенные многоуровневые наборы данных появились ещё в COBOL и оттуда перекочевали в PL/1. Структуры в современном виде появились не позднее 1967 года — достаточно посмотреть на Simula-67 и Algol-68.
вероятно стоит заметить, что разработка "C" велась параллельно с написанием компилятора, для чего использовалось подмножество самого "C", техникой bootstrapping, когда новые конструкции языка последовательно реализовывались в компиляторе, который затем переписывался сам используя это расширение в новой версии кода, движеие было "BCPL->B->NB->C" с многими промежуточными версиями, участие Strachey в создании "C" было не прямое, скорее через влияние на дизайн BCPL и свою работу "Fundamental Concepts in Programming Languages"
Это сделало Unix намного более переносимой на разные машины и способствовало её популярности. Без Unix у нас не было бы всех прекрасных современных операционных систем — вспомните Linux...
В Linux нет ни строчки кода из UNIX, так что нет никаких оснований полагать, что без UNIX у нас не было бы Linux.
Если же считать «идейное влияние», то в список «наследников UNIX» можно включить и DOS и Windows ровно на тех же основаниях, как и Linux — тем более, что в Windows куски кода UNIX (с копирайтами The Regents of the University of California) доподлинно есть.
Без UNIX операционная система Linux выглядела бы совсем по-другому, и даже название было бы другим. Можно ли гипотетическую систему с другим API, другой оболочкой и другим названием считать всё тем же Linux?
API-ем и оболочкой от UNIX вдохновлялся в т.ч. MS-DOS 2.0: www.os2museum.com/wp/dos/dos-2-0-and-2-1 — но почему-то не вижу MS-DOS в списке «наследников UNIX». Ещё больше ими вдохновлялась WinNT, в которую добавили Berkeley sockets.
Эм, достоинство Unix в удобной и легковесной абстракции, в т.ч., например, "все есть файл". И Linux и куча встраиваемых систем на его основе появились именно благодаря этим фичам.
Потому что Томпсон заменил выкидываемый Multics именно на UNIX (в 18к оперативки), а другим понравился именно его подход. При этом тогда был де факто оупенсорс и система была почти везде - поэтому ее начали копироывать.
Правильная постановка утверждения: если бы не было Томпсона, Ричи, университетского оупенсорса и юникса, то роль linux занимала бы другая система.
P.s. а Multics на момент принятия решения Томпсоном был недостаточно портабельным и слишком монструозным.
Потому что Томпсон заменил выкидываемый Multics именно на UNIX
не совсем так, или даже совсем не так,
Томпсон (как и Ричи) работал на Bell Lab, Multics разрабатывался для машин GE и Honeywell, соотвественно судьбу Multics решали люди из этих компаний, Bell Labs решила выйти из проекта в 1969, естественно Томпсон и Ричи вышли тоже, и стали заниматься другим по программе Bell (это в конечном счете привело к Unix и пр.), в то время как GE, MIT, Honeywell продолжали работу над Multics без них и довели до ума, всего было продано порядка 80 систем, каждая стоимостью >$1M, Multics даже прошел сертификацию уровня B2, был первой OS такого уровня защиты, сложность разработки в большой степени зависела именно от этих требований, Multics устанавливался на новые системы, чуть ли не до 1990 года, в основном тем организациям, для кого такая сертификация была обязательной, кстати его резидентое ядро было < 200KB (сравните с Linux), как обычно строго imho
Отлично, но абстракция «всё есть файл» в UNIX пришла из Multics, где применялась ещё шире — блоки памяти тоже были файлами
Основным отличием Unix от Multics был, насколько я помню, Kernel Panic вместо обработки исключительных ситуаций. Дело в том, что больше половины кода Multics составляли именно алгоритмы обработки ошибок. Поэтому создатели Unix не мудрствуя лукаво решили примерно в таком ключе: "все равно много проблем можно решить простой перезагрузкой, поэтому не будем усложнять"
И в этом смысле иронично, что
но DOS и Windows были бы?
точно не являются правдой на 100%, ведь Windows знаменит прежде всего своим аналогом Kernel Panic (я сейчас, конечно же, про BSOD), который был основным отличием самых первых юниксов от мультиксов.
Примечательно, что именно по причине ненадобности в C не внесли никакой обработки исключительных ситуаций, кроме кода возврата ошибок errno. И в этом плане Unix оказал значительное, историческое влияние на вычислительные системы в целом.
В DOS же файловая концепция никсов зашла уже через пару лет после её создания, ко второй версии. До этого там была сугубо СР/М-ная архитектура. Поэтому она вполне существовала бы и без влияния UNIX, просто развивалась бы в другом ключе. Ну а Windows вообще зашла с другой стороны, изначально как GUI над существующим DOS API.
Linux, очевидно, не был бы таким, т.к. его киллер-фичей была Unix-совместимость. DOS, очевидно, был бы таким, т.к. подавляющему большинству его пользователей было глубоко начхать, что там у него под капотом. Никто, кроме разработчиков, и не заметил переход от FCB к дескрипторам. А то, что пайпами в DOS стало можно объединять потоки вывода и ввода двух приложений, ну так и про это мало кто знал :)
достоинство Unix в том, что OS проектировалась как portable с самого начала, и начиная с 4th Edition (1973) была написана на C (вероятно третья OS написанная на языке высокого уровня, после Burroughs MCP на extended Algol, и Multics на PL/1), была открыта, и нормально документирована, это сделало Unix удобным для использования/изучения в университетах и колледжах, и широкому использованию, что создало условия для появления Linux (сначала на PC, а затем embedded), и всей дальнейшей истории с этим связанной
Если бы С/С++ был плохой то тогда компиляторы С/C++ писали бы на более удобных и "популярных" языках с синтаксисом типа Prolog, Python.
Но в текущей реальности, для написания OS/RDBMS/JVM/CLR RT используют где-то чистый С где-то С/С++.
Проблема с индексами 0 или 1 решается просто если использовать слово не первый, а начальный элемент. Т.е. фраза начальный элемент имеет индекс 0, не вызывает отторжение и двузначность.
Я ни разу не видел чтобы при расчете на первый второй кто-то в середине начинал говирить что он не первый а N-й. Т.е. это просто условные договоренности, и обвинения что элемент массива должен начинаться с 1-цы, выглядят проявления эффекта утки.
безопасного языка
вот это конечно смешно
Единственная задача, с которой он справился, это быть переносимым ассемлером. UEFI EBC, TenDRA ANDF, Dis VM, LLVM, WebAssembly, PNaCl все в чём-то сильно уступают. Наверное, лучшей попыткой был TenDRA ANDF, но что-то компиляторов под него негусто, а вот для Си процесс пошёл, и поверх него и Ада есть, и Eiffel, и Oberon. Пусть там каждое сложение с проверкой переполнения многословно кодируется, но хоть как-то это работает.
Было интересно почитать статью. Спасибо!
То самое, когда удачно сошлись и время, и место, и человек.
Как школьный учитель изобрёл один из самых влиятельных языков программирования