Comments 104
И мечтаю о прочтении чего то современного на тему и в том же прикладном качестве (практической полезности) как:
Ну, межмодульные связи издавались и во Всесоюзном издательсте под названем "Комплексирование программ в ОС ЕС".
Напишем, проблем нет.
Здоровое любопытство — это здорово!
Куда только не заводит здоровое любопытство.
Жив курилка:
В 1984 году при своем выпуске это был компилятор для MS DOS версии 1.0 и IBM-PC /XT.
Мы тоже в 1987 году искали исполнителя для разработки транслятора PL/1 для ЕС-184x. Но главное направление было все же Си. PL/1 мы так и не заказали и я был этому рад.
В классическом высший пилотаж подзадачи, асинхронный ввод вывод, динамические массивы, базированные структуры с произвольным побитовым формированием полей и волшебным Структура A = Структура B BY NAME. Отложенная обработка (т.е. не критичная по времени) непрерывно от испытания к испытанию меняющейся структурой кадра телеметрии была праздничной. До того как я подсунул вот это BY NAME под каждое испытание писали и отлаживали фактически новую программу на ассемблере. А так описал места битовых кусочков информации в одной структуре и пригодные типы для последующей обработки в другой одинаковыми именами и пусть компилятор работает. А время было тяжёлое, 16-ти бит телеметристам не хватало катастрофически. В одном легендарном ЗАТО в середине 80х проводили конференцию по унификации и стандартизации и при подготовке насчитали 16 способов представления 16-ти разрядного отрицательного числа встреченного при обработке. т.е. задействовать все 16 разрядов а знак разместить там, где получится или вообще ни где, по контексту должны догадаться при обработке.
P.s. И за «Межмодульные связи в ОС ЕС» именно в этом издании снимаю шляпу. В числе самых полезных книг моей жизни она.
Хорошо организованный справочник и для начального ознакомления и для практической работы. Практически полное описание языка и библиотек.
Всё же это тоже ценность, когда язык можно прочитать и выучить весь. 20-30 или около этого страниц — это здоворо!
Спасибо за перевод! Один минус, что текст отформатирован неважно. В оригинале ключевые слова выделены, есть абзацы. Думаю, тут следовало хотя бы удачнее разделить текст на блоки.
Конечно в Си есть некоторые архитектурные недостатки, понятно что на момент его создания еще не было такой отработанной базы концепций и парадигм как сейчас. Но такой маленький объем и простота — вот к чему надо стремиться.
Так значит прав Эндрю Таненбаум, когда писал:
Акцент делается на чтении программ на Си, а не на написании кода.
Конечно, не очень. Но ведь влпрос в том с какой целю написан этот код и какую задачу решает. Ведь Ритчи писал язык для разработки операционных систем, значит он должен был и максимально эффективен с точки зрения использования компьютера.
Работа над языком Си началась в 1969 в рамках написания с Кеном Томпсоном игры "Космический полёт". Одновременно Томпсон запилил свой Юникс, изначально не связанный с Си и Ричи никак. Когда язык был уже готов и представлял собой шедевр, в 1972, Томпсон попросил взять его для. 3й редакции Юникса, а 4ю просто переписал на Си (90% сишного кода). У меня такий сведения про появление Си.
Язык С не представлял собой никакого "шедевра" в 1972, а являлся в то время довольно неудачной поделкой, сделанной впопыхах и на коленке. Главным образом именно поэтому уже первое издание K&R полностью переработало и синтаксис, и семантику языка, отказавшись от большого числа "странных" низкоуровневых свойств языка С образца начала 1970х. С некоторой натяжкой "шедевром" можно назвать K&R C времен первого издания книги. Но настоящий С родился только со вторым изданием K&R, появившимся почти одновременно со стандартом C89/90.
Чтение кода на любом языке программирования определяется в первую очередь "словарным запасом" из достаточно легко распознаваемых идиом, накопленным читателем. Ваш пример я прочту совершенно без запинки и без напряжения.
P.S. В своё время не смог осилить книгу Стерлинг Л, Шапиро Э «Искусство программирования на языке Пролог»
Я думаю нет, не было. И мы, когда начали создавать СИМ/САИПР не рассматривали его как язык разработки. С нас требовали ПЛ/1. В СССР пик популярности Ады совпал не только с развалом СССР, но с началом продвижения языка Си. А с ним Ада поспорить не могла, прежде всего из-за отсутствия компиляторов. И тут наступила эра персоналок и MS Windows и, естественно, Си. И Ада канула в Лету.
Вы сто раз правы:
У нас почти нет нужды в серьезных системах — промышленности-то почти нет, а что есть — там все устарело…
У нас принимают законы на полном серьезе, как шрафовать просто за курение, а не за то, что по чьей-то вине (кто-то позволил за копейки лес вырубить, кто-то не почистил русла рек, да малоли чего) затапливает города.
Ай, даже не хотется обсуждать это. Была бы серьезная потребность, давно бы и ОС свои были!!
Был разработан по заказу Пентагона для замены языка COBOL. К компиляторам предъявлялись очень жёсткие требования на соответствие стандарту, в частности для исключения возможности образования диалектов, что сильно затрудняло процедуру сертификации. На эту тему расскажу байку.
В начале 90-х летел в самолёте. Мужик в соседнем кресле работает на ноутбуке (тогда ещё назывался лэптоп). Вижу, что у него в окошках тексты на Аде.
Вежливо интересуюсь: «О, у Вас есть компилятор с Ады?».
Гордо отвечает: «Это Я — компилятор с Ады!».
Оказалось, что в их организации (не знаю, какое подразделение НАТО) требуют программировать на Аде, а сертифицированного компилятора нет, и чтобы как-то работать в качестве компилятора используют живого человека. Бывало и такое.
В начале 90-х компилятор с Ады был не проблемой. У нас он работал даже на ЕС 1841.
Читал. И она у меня до сих пор в библиотеке. А ещё Н. Джехани «Язык Ада». И не очень известная в СССР/России (не переводилась) Serafino Amoroso, Giorgio Ingargiola «ADA. An Introduction to Program Design and Coding».
Вообще-то, если ты программист, то какая разница на каком языке писать код!
Если он профессиональный программист, то он прочитает описание языка
Написать — сможет. Эффективно, быстро, читабельно, безопасно — это уже вопрос.
Я уже не раз сталкивался, как люди пишут, я читаю, говорю: у тебя тут UB, на что ответ: "Ну и что? Работает же!" А потом… другая ОС, другой компилятор и… А почему это не работает. Или… просто компилятор тот же обновился.
Мне кажется, что если хорошо знать с++, то остальные языки будет намного легче понять.
И даже Forth, Prolog, Erlang или Haskell?
Вообще, по моим наблюдениям, люди, утверждающие в стиле «хорошему программисту должно быть без разницы, на каком языке писать», зачастую просто плохо представляют, насколько другими могут быть языки.
Вопрос эффективности — это использование по целевому назначению. Далеко не всегда нужно оперировать терминами тактов или типами барьеров памяти. Есть предметные области, в которых просто закопаешься, если будешь об этом думать, а задачу не выполнишь. А когда упрёшься — профилировщик и думать.
Та же Ява, да в тырпрайзе, у тебя сами сети передачи данных такие задержки дадут… А упираешься в производительность железа, в зубы JNI и переписывай узкое место, и считай такты, и учитывай барьеры.
Ну и пишут они, всё же, для JVM, что бы код был эффективным с её точки зрения. А дальше уже задача разработчиков JVM, что бы сгенерированный байт код эффективнее работал на конкретной платформе. Т.е. ты спрашиваешь ответа не у тех людей.
Вообще-то, если ты программист, то какая разница на каком языке писать код!Сильное утверждение. Я бы его смягчил в духе Генри Форда («Any customer can have a car painted any color that he wants so long as it is black.») в такой редакции:
Если ты программист, то какая разница на каком языке писать код,
до тех пор пока это язык Си.
Именно потому, что я Программист и знаю Си, мне без разницы на каком языке писать.
А про Генри Форда красиво.
P.S. В выше комментарии был именно акцент, пока язык Си (Си подобный) или не так?
Могу еще добавить tcl, perl, python (что там еще), modula, Алмо… И никакого акцента на Си. Я начал программировать тогда, когда еще не было Си в учебных программах.
— В статье, автор упомянул PL/1, на днях читая на опеннете новость про Rust 1.37 "… Дополнительно можно отметить начало тестирования проекта Async-std, предлагающего асинхронный вариант стандартной библиотеки Rust (порт библиотеки std, в котором все интерфейсы предложены в версии с async и готовы для использования с синтаксисом async/await). " в очередной раз вспомнил как был в середине 80х бит(фигурально) в курилке за асинхронный ввод вывод при работе с лентой на PL/1, ибо лента крутится быстро быстро, а терминалы с Primus все висят. ))))
Безнадёжно пытаюсь вспомнить, как (без интернета) я на рубеже 80-90х узнал о существовании Си Транслятора от НИЦЕВТ ( www.nicevt.ru ).
В 1987 году мы начали создавать СМИ (стенд имитационного моделирования по программ) антиСОИ:
Встал вопрос на чем разраатывать? Мой ответ был — это будет Unix и язык Си.
Ни того ни другого я еще не держал в руках. Все упивались PL/1 и ОС ЕС.
Все страшно удивились, как так, по твоим книжкам учат программированию на PL/1.
Но я стоял твердо: либо так либо я не берусь за это дело. И знаете где мы взяли и Си и Unix.
Юних для больших ЕС ЭВМ мы взяли в НИЦЭВТ-е под названием МОС ЕС и там уже был Си. А для первых персоналок ЕС-1840 — это был Minix от Эндрю Таненбаума с компилятом Си. Вс это было в 1987 году. Вы не поверите, прошло лет 15 и нашлись люди, которые подошли по мне и сказали как здорово, что вы настояли тогда на Юниксе и Си, а то где бы мы были со смоим ПЛ/1.
Вот такая история
С такими замечательными игрушками помимо прочих.
pce-0.2.2-xt-xenix86-2.1.3.zip An IBM PC/XT 5160 with SCO Xenix System V 2.1.3
pce-0.2.2-xt-minix-1.1.zip An IBM PC/XT 5160 with MINIX 1.1
pce-0.2.2-xt-minix-2.0.2.zip An IBM PC/XT 5160 with MINIX 2.0.2
P.s. Кстати Xenix видел живьём, ставил не я, но совсем чуть чуть по клавиатуре по ходил пальцами. В память врезалось удивление двухпанельным файловым менеджером (mc ли это, не помню) на янтарном геркулесе.
P.s. Кстати Xenix видел живьём
Я на нем работал. Были первые первые персоналки PC/XT. Как я уже сказал, все решено было делать на Unix, но мы никак не могли получить во НИЦЭВТ МОС ЕС для персоналок и тогда было решено начинать разработку на Xenix. Хорошая система была. Нашими исполнителями была группа разработчиков из ИПМ АН СССР, возглавляемая профессором Трахтенгерцом Э.А.
Вероятно с оплатой или ещё с какими то официальными действиями проблемы таки возникли и интересно это было мне одному, а транслятор достался как бы с временной лицензией. Т.е. стояла проверка на дату после которой он должен перестать работать. Большая красивая ОС СВМ(ПДО) на ЕС1060 мне позволила найти это место и УКРАСТЬ(каюсь публично) Си у НИЦЕВТа. Может и было потом что то оформлено, не помню, моя судьба вместе с судьбой страны резко поменялась.
Если продолжить вечер воспоминаний, то выше я про PL/1 и ленту писал. Так вот лента была с телеметрией «Изделие 171» до перевода испытаний на Камчатку.
Ну а с Unix(ДЕМОС) ещё веселей, уже будучи почти свободным не советским «художником», за наличные рубли одного маленького банка, покупал у М.Коротаева дистрибутив для СМ1425(pdp1173) в знаменательный день. В день когда Демосу(фирме) отрубили канал, утром был у них в офисе, не зная, что Михаила нужно искать в АО Релком, которому и перешли права на канал в Европу. Поздно вечером, мы таки встретились в офисе Релкома и я попал на фуршет по случаю. )))
p.s. И это всё про Си из прошлого века…
Прямо про меня. Только бы добавил Весну и СПЭМ-80, М-220 и Мир, а также автокод и Алмо, и кто тут говорит, что «текст на Си плохо читается»?
habr.com/ru/post/464075/#comment_20521017
p.s. с цитированием я пока не разобрался… :(
p.p.s С первых дней знакомства у меня была необходимость и возможность благодаря Си писать сразу для 32-х,16-ти,8-ми — разрядных разных систем(и железо и ос) на одном языке и это было волшебство!!! Это забыть не возможно.
Мне кажется после любого ассемблера СИ воспринимается, как огромное счастье. У меня были Z80, PIC и i8086. СИ после них это как другой мир.
а таблички машинных кодов в журнале Радио середины 80х годов? я тогда в библиотеке повырезал из некоторых журналов и стащил домой читать-разбираться, дико каюсь-извиняюсь перед библиотекарями, но думаю, в то время и в том месте это все равно кроме меня никому не интересно было, с утра в очередь за молоком стояли.
Как я вас понимаю.
Вот этим и хороща была книга Эндрю Таненбаума «Operating Systems Design and Implementation» ее первое издание, что в ней было описание и Си и процессора 8088 (стр.363-370). Кстати, тоже можно перевести.
в C99 есть инициализация полей структуры по их именам:
struct mystuct {int a; long b;};
struct mystuct ms = {.a=1, .b=2}; // C99 initializing by names for more readable
struct mystuct ms2 = {1, 2}; // general initializing by values
struct mystuct ms3 = {a:1, b:2}; // obsolete initializing by names
PS: чаще использую инициализацию по значению, хотя более читабельно по именам конечно же...
приходится пользоваться более старыми компиляторами
Если речь о GCC/Clang, то с ними проблем и нет, только придется собирать в режиме gnu а не std. с Visual C++, да, беда.
у нас ведь уже есть initializer_list (с оговоркой того что только по значению инициализация а не по именам, ну и как бэ -std=C++11)
я сам ещё в своих поделках не применял, но весчь оч полезная ;)
К сожалению даже в C++20 она пока выглядит не тортово:
struct mystuct {int a; long b;};
struct mystuct ms = {.a=1, .b=2}; //как в С, всё ок
struct mystuct ms2 = {.b=1, .a=2}; //а хрен тебе, а не как в С
//error: designator order for field 'mystuct::a' does not match declaration order in 'mystuct'
struct mystuct ms3 = {.a=1};
struct mystuct ms4 = {.b=1}; // так нормально
char map[256] = {['1'] = 1, ['2'] = 2,};
Удобно когда нужно инициализировать только некоторые элементы.В крестах такого нет.
Еще по-моему в крестах нет __VA_ARGS__.
Еще по-моему в крестах нет __VA_ARGS__.С C++11 есть.
Ради формальной корректности стоит заметить, что ни в С, ни в С++ не существует способа "инициализировать только некоторые элементы" агрегата через посредство {}
-инициализатора в объявлении. Инициализированы в вашем примере будут все таки все элементы без исключения. Т.е. элементы, для которых вы не указали инициализатора, будут инициализированы нулями.
Это верно. Но во некоторых случаях это выливается в неприятный удар по производительности кода у ничего не подозревающего автора. Что-то вроде
char buffer[1024] = { [0] = '?' };
В тех случаях, когда производительность критична, а полная инициализация нулями не требуется, бывает разумнее прибегнуть к объявлению без инициализатора и последующему выборочному присваиванию.
На некоторых платформах с ограниченными ресурсами такая инициализация также может быть нежелательна из-за того, что "образ" всей инициализированной структуры попадает в сегмент инициализированных данных, тем самым раздувая размер этого сегмента. Объявление без инициализатора и с последующим выборочным присваиванием свободно от этого недостатка (по какой-то причине мейнстримовые компиляторы не делают такой оптимизации).
struct mystuct ms2 = {.b=1, .a=2}; //а хрен тебе, а не как в С
//error: designator order for field 'mystuct::a' does not match declaration order in 'mystuct'
На самом деле пофиг, не так страшно. Хотя бы вообще завезли и можно параметры пропускать.
Да, помню наше обсуждение с ссылкой на этот отрывок. Он производит сильное впечатление, хотя и является только наводкой на Си для незнакомых с ним программистов, а не цельным введением.
for(;;) { ... }
работает как бесконечный цикл с выходом из середины.Ерунду написал. Проверил в GCC; оказывается, пустое условие разрешено только в «for». В while и if пустое условие вызывает ошибку синтаксиса.
Книга представляет лишь исторический интерес, ибо как и в K&R, львиная доля изложенной информации уже давно относится к категории "это было давно и не правда". Также налицо несколько ошибок/упрощений, допущенных автором.
Кстати, вы перевели термин "statement" как "оператор", что является неприятной особенностью многих переводов книг по С и С++ на русский язык. Возникающая при этом неоднозначность между терминами "statement" и "operator" совершенно неприемлема в серьезной литературе. Также, в начале "А.4. Операторы" вы внезапно перевели один из "statement" как "утверждение", что только добавило путаницы.
Книга представляет лишь исторический интерес
Но ведь именно об этом и сказано в статье:
Это описание интересно также и с исторической точки зрения и для понимания того, как далеко ушел язык Си с момента своего рождения и IT-отрасль в целом.
Только без всякого лишь.
Насчет "утверждения" и "оператор" полностью с вами согласен и поправил. Спасибо.
А вот насчет
как и в K&R, львиная доля изложенной информации уже давно относится к категории "это было давно и не правда"
позволю с вами не согласиться. Классика бессмертна.
Классика бессмертна.
Я немного удивился, когда узнал что компиляторы до сих пор поддерживают такой синтаксис:
int main(argc, argv)
int argc;
char *argv[];
Но так уже почти никто не пишет.Еще неявный int был убран из C99, но от компиляторов больше варнинга ничего не увидишь. И так тоже не пишут.
В принципе
З.Ы. Почему то в старых сорцах сорцах постоянно вижу выражение у return в скобках, несовместимости конечно никакой нет, но просто интересно, зачем так делали? Это синтаксис раньше такой был? Или это чтобы return можно было макросом заменить?
Я немного удивился, когда узнал что компиляторы до сих пор поддерживают такой синтаксис:
int main(argc, argv)
int argc;
char *argv[];
Я тоже удивился и бросился проверять. Проверил и успокоился: преемственность обеспечена!
Этот синтаксис (так назывемый "K&R синтаксис") объявления функции был официально объявлен obsolescent (т.е. подлежащим удалению из языка) начиная с самого первого стандарта С. Однако ни у кого не поднимается рука его фактически удалить, ибо обратная совместимость с тоннами старого кода до сих пор важна, а переписывать его никто не хочет.
Кстати, я смотрю, кого-то удивила продолжающаяся поддержка этого синтаксиса. Но на самом деле всякий раз, когда в программе на С вы описываете параметры функции как ()
(пустые скобки), вы используете именно этот устаревший K&R синтаксис. Это его частный случай. В современном синтаксисе не допускается ()
, а требуется именно (void)
.
Неявный int действительно убран из языка. И в языке С нет "варнингов", а есть только диагностические сообщения. Как только компилятор выдал требуемое стандартом диагностическое сообщение в ответ на некорректный код, язык С на этом заканчивается. Дальше остаётся только самодеятельность вашего компилятора, к языку С никакого отношения не имеющая. Современные компиляторы С вам и указатели никак не связанных типов тоже разрешат неявно друг к другу приводить (с "варнингом"), хотя язык С это явно запрещает.
Это ключевой момент в поведении большинства современных мэйнстримовых компиляторов С: в первую очередь это компиляторы огромной по своему объему устаревшей и довольно низкокачественной базы унаследованного кода, написанной на некоем развеселом С-подобном языке. И только во вторую (если не в пятую) очередь эти компиляторы вспоминают собственно о самом чистом языке С. В частности, в gcc язык С начинается с флагов -std
и -pedantic
(лучше — -pedantic-errors
). А то, что вы получаете в режиме по умолчанию — это не С, а некий студенческий С-подобный суржик.
Устаревшее в вышеприведенной книге еще есть и еще. В частности, утверждение о невозможности передачи структур в качестве параметров и возврате их из функций (хоть автор и замечает, что "некоторые компиляторы позволяют").
Интересным является утверждение "Каждая глобальная переменная должна быть объявленным ровно один раз без атрибута extern, чтобы выделить память под нее." Это действительно так и стандарт языка требует единственного определения. Однако компиляторы, произрастающие из Юникс (в частности, gcc), всегда игнорировали это правило и позволяли множественные определения переменных, раскиданные по программе. Компиляторы с других платформ как раз выступали за единственность определения, ибо глобальный поиск и удаление лишних определений — неоправданно трудоемкая операция (по меркам тех времен). В конечном итоге победили последние, а не юниксоиды: стандарт С возлагает заботу о единственности определения на автора кода.
А что касается синтаксиса с операндом return в скобках — это было требованием в первых версиях языка С образца начала 70х. Отменилось это требование только в K&R. Скорее всего этот синтаксис было просто тупо унаследован из предшественников C: языков B и/или BCPL.
del
Поспорю с вами и с уважаемым TheCalligrapher по поводу переводов. Увы, но неприятной особенностью переводов англоязычной литературы по C/C++ на русский язык является вовсе не перевод “statement” как “оператор” (что абсолютно правильно, и именно так и должно переводиться). Ужас переводов на русский — это перевод “operator” как “оператор”. Именно из-за последнего и приходится горе-переводчикам либо плодить откровенно корявые “утверждение цикла for”, “утверждение условный оператор if”, либо создавать путаницу “операторов” (которые по-русски получаются все — операторы, а по-C — совершенно разные сущности языка) — “оператор for” и “арифметические операторы”.
Я, глядя на очередной перевод книги по C/C++, в первую очередь обращаю внимание на перевод трёх чаще всего путаемых горе-переводчиками слов — expression, statement, operator. И если в переводах путаница, и/или они не соответствуют:
expression — выражение;
statement — оператор;
operator — операция,
то мой вердикт однозначен без собственно чтения книги — “Читайте оригинал или ищите другой перевод”.
Увы, но ваш перевод попадает именно в категорию “читайте оригинал или ищите другой перевод”. Именно потому, что у вас, например, for(;;) | if() | + | =
— всё операторы, но если читать оригинал, то первые два будут statements, а последние два — operators. И в результате того, что вы их смешали одним русским словом “оператор”, в одном месте вашего перевода вообще катастрофа — “выражения состоят из операндов и операторов” (An expression is a sequence of operators and operands that specifies computation of a value...) А покажите выражение из операндов 3.141592
и 2.718281
и оператора цикла :)
А условный оператор — это что? Это “if”
или “?:”
? Надо догадываться “из контекста”? Нет, друзья мои, язык C всё определяет чётко. Первый — selection statement (оператор), второе — conditional operator (операция).
В настоящее время язык широко используется в различных областях.
Интересно что это за абстрактные области такие?
Как по мне, кроме программирования микроконтроллеров и Linux модулей язык C никому с доплатой больше не нужен.
Да и из разработки на микроконтроллерах язык С уже активно вышибают кодом на С++. В евро союзе дак, уже давным-давно микроконтроллеры программируют на С++ 17+. причем даже для Automotive ECU
Cи остался только в Linux ядре.
Введение в Си. Послание из прошлого столетия