?

Log in

No account? Create an account

Share Next Entry
Почему Си?
avchernov
Дискуссия "Паскаль против Си на первом курсе ВМК МГУ", которая на протяжении последних двух-трех месяцев шла кулуарно, наконец вышла на просторы интернетов. Начало этому положил Андрей Столяров, опубликовав у себя на сайте эссе на тему недопустимости начального обучения программированию на Си, которое, видимо, против воли автора, оказалось даже на хабропомойке. Должен признаться, я являюсь одним (а может и единственным) из тех самых коллег, вопросы которых и послужили отправной точкой к дальнейшей дискуссии и вылились в написание этого эссе.

Я не собираюсь соревноваться в литературном и полемическом мастерстве с Андреем, но считаю необходимым ответить на его эссе своим текстом, в котором постараюсь обрисовать, почему я считаю полезным и даже необходимым не только кардинально изменить преподавание программирования в 1 семестре ВМК МГУ, но и перейти на преподавание Си вместо Паскаля.

Должен сразу сказать, что этот текст - не повод устраивать войну "Си против Паскаля", либо какую-либу другую войну. Кроме того, попытки меня переубедить бесполезны. Для себя я вопрос решил. Поэтому я оставляю за собой право произвольно удалять комментарии, которые сочту неуместными.

Для начала краткое описание текущего положения дел в преподавании программирования на ВМК МГУ. Базовые курсы программирования читаются первые 4 семестра до распределения студентов по кафедрам для дальнейшей специализации.
Курс первого семестра называется "Алгоритмы и алгоритмические языки", и именно об этом курсе пойдет речь в дальнейшем. В программу курса входит теоретическое введение в алгоритмы, язык Паскаль и базовые алгоритмы. Второй семестр посвящен архитектуре ЭВМ. В рамках семестра изучается язык ассемблера для архитектуры i8086. Третий семестр - это операционные системы на примере Unix и язык Си как язык системного программирования. Четвертый семестр - язык Си++ и всякая всячина от основ теории формальных грамматик до параллельного программирования на OpenMP. Надо сразу отметить, что единственный более или менее поставленный на современном уровне семестр из этих четырех - третий, там где про Си и Unix.

Это - программа. Теперь о том, что из всего этого получается. Я на протяжении достаточного количества лет веду занятия на втором курсе. Предполагается, что на входе мы получаем студентов, освоивших алгоритмизацию и язык паскаль, а так же имеющих представление об архитектуре ЭВМ. Однако действительность такова, что многие студенты не в состоянии уверенно написать ни один из алгоритмов сортировки массива, а те, кто в состоянии, в большинстве своем пришли с этими знаниями еще из школы. Способ реализации очереди с помощью "кольцевого буфера" для них оказывается новым, а вопросы "что такое тип данных" или "соглашение о вызовах" вводит их в ступор. То есть, ни о каком уверенном освоении алгоритмизации говорить не приходится. Во многом получается так, что первый курс оказывается просто потерянным.

Почему так? Я попытаюсь перечислить ряд причин, без претензий на полноту и без выделения их важности.

Первая причина - это ориентация на "программирование на бумажке". Из 7 часов программирования в неделю в 1 и 2 семестрах (3 ч. лекции + 4 ч. семинары) только один час в неделю отводится на практические занятия в машинном зале. При этом в сентябре занятий в машинном зале не предусмотрено, так как изучается машина Тьюринга и алгоритмы Маркова. Оставшийся один час в неделю посвящен выборочному приему заданий. Таким образом, студенты не пишут программ в учебное время в машинном зале.

Вообще программирование на бумажке представляется мне анахронизмом эпохи перфокарт и компьютерных классов на 15 человек. Выписывание алгоритма на бумаге во многом принуждает следовать синтаксической структуре программы (сначала переменные, потом - процедуры, потом - основная программа), а не формулировать алгоритм так, как это удобно.

Вторая причина - это изучение так называемого "стандартного паскаля" на лекциях. Стандартный паскаль - язык заведомо мертвый. Из популярных реализаций паскаля ни Borland Pascal, ни Free Pascal, ни Delphi даже и не пытаются этот стандарт поддерживать. В результате возникает очень странная ситуация, когда, рассказывая на семинарах о тех или иных возможностях реализации (например, о работе со строками), оговариваются, что на экзамене это использовать нельзя, поскольку данная возможность не входит в "стандартный паскаль".

Дублирование изучения языка на лекциях и на семинарах (причем дублирование заведомо конфликтующее там, где "стандартный паскаль" не совпадает с используемыми реализациями) приводит к тому, что на лекциях не остается времени на изучение алгоритмов. Так, из лекционного курса совершенно выпадает тема об алгоритмах на графах, хотя она входит в основную часть темы Algorithms and Complexity СС-2008.

Третья причина - это чехарда языков программирования. К ней мы еще вернемся.

Что же предлагается сделать? Во-первых, убрать из лекционного курса лекции, относящиеся к языку программирования. Изучение языка программирования полностью перенести на семинары. Начать изучение языка с самого первого занятия и не тратить время на изучение на семинарах машины Тьюринга и прочего. Таким образом, к моменту завершения вводной части курса, посвященной теории алгоритмов, студенты будут достаточно подготовлены к восприятию алгоритмической части курса.

Да, я считаю, что изучение машин Тьюринга и прочих формальных схем не настолько важно, чтобы тратить на это драгоценное время семинарских занятий в сентябре. Для освоения достаточно задач, выдаваемых в качестве заданий.

Во-вторых. Я считаю, что выработка устойчивых навыков программирования и алгоритмизации достигается только написанием программ. Программы бывают двух видов - правильные и неправильные. Промежуточных градаций не бывает. Поскольку речь идет об учебных заданиях консольного характера, допустимо исчерпывающее тестирование задач на тестовых наборах. Да, речь идет об автоматической проверке сдаваемых задач. Автоматическая проверка обязательно должна сопровождаться просмотром исходного кода программы и отправкой программы на доработку в случае малейших замечаний.

В-третьих, с самого начала необходимо формирование навыков тестирования своих программ, если угодно, юнит-тестирования. Задания не должны приниматься, если к ним отсутствуют тесты, покрывающие все возможные случаи входных данных. Кроме того, отдельный тип заданий может заключаться именно в разработке системы тестов для тестирования программ.

Все вышесказанное не требует для своей реализации отказа от языка Паскаль. Однако, если ли смысл сохранять Паскаль? Все единодушны во мнении, что знание языка Си необходимо для специалиста в области Computer Science. Необходимо ли знание Паскаля? Да, в-общем, нет. Это подтверждается и дальнейшим обучением на ВМК на 3 курсе и выше.

Примерно два года назад на ВМК проводилась так называмая срезовая контрольная, где пятикурсников просили, среди прочего, решить простую задачу. Кроме того, на письменных вступительных экзаменах в аспирантуру тоже каждый год дается простая задача на написание программы. Доля решений на паскале и производных в общем потоке ничтожна. Практически все решения пишутся на Си, Си++ или родственных языках.

Когда же дело доходит до 3 семестра, примерно половина семестра тратится на обучение студентов языку Си. И это вместо таких важнейших тем, как, например, нити и многопоточное программирование.

Вместо года, потраченного на изучение языка, который потом ни в каком виде не пригодится, мне кажется предпочтительнее с самого начала изучать необходимый и практически важный язык. Проблемы начального старта в Си преодолимы, а дальнейшие достоинства (или недостатки) языка мне представляются несущественными.

Далее я хотел бы по пунктам ответить на аргументы Андрея из его эссе.

2. На кого ориентироваться

Конечно, пусть пренебрежительно-высокомерное отношение автора к школьным учителям информатики останется на его совести, не это главное.

Автор пишет: «если вчерашний абитуриент умеет программировать — это, прежде всего, означает, что программированию он может учиться самостоятельно, без всякой помощи со стороны преподавателей». Я позволю себе заметить, что существенная часть контингента поступающих на факультет ВМК МГУ приходит из школ, где обучение программированию поставлено очень хорошо. Это — СУНЦ МГУ, 179, 1543 и другие московские школы, я уж не говорю о немосковских школах (я их не очень знаю). Этих людей именно учили программированию, и учили по насыщенным и содержательным программам. Существенная часть контингента набирается по результатам олимпиад по информатике (реально — программированию) разного уровня. Чтобы успешно участвовать в олимпиадах и получать на них дипломы все-таки как-то надо уметь программировать. Суммарно я бы оценил контингент первокурсников, уверенно умеющих программировать, в 25-30%. И это очень прилично.

Кроме того, неуместно и пренебрежительное отношение к ЕГЭ. Чтобы написать ЕГЭ по информатике на серьезный балл нужно иметь какое-то понятие о программировании и о языках программирования. Вполне можно считать, что первокурсники может и не владеют уверенно, но хотя бы что-то слышали о переменных, типах переменных, присваивании, условном операторе. Это все не будет для них совершенной новостью.

Поэтому, общий вывод второго раздела просто неверен. Ситуация уже давно изменилась. Те, у кого нулевая информатика в школе, либо просто не идут на ВМК, либо занимаются дополнительно где-то еще.

3. Hello, world

Завязанная на ключевой тезис о «програмистской невинности» первокурсников дальнейшая критика Си немедленно начинает пробуксовывать. 90% аудитории имеет хоть какое-то понятие о программировании, и даже если мы захотим погружаться в объяснения о функциях, типах возвращаемых значений и возврате значений, все будет воспринято не так катастрофично, как описывает автор.

Кроме того, я не вижу ничего страшного в том, чтобы сказать «пока надо так писать, все поймете потом». Выскочек, которые, очевидно, самоутверждаясь, будут выступать с вопросами «а можно ли без #include» можно и нужно давить в зародыше. Ничего хорошего дискуссия с ними во время занятия не принесет.

Проблема с пресловутым символом \n решается на удивление просто, вместо printf достаточно использовать puts. А именно,

puts(“Hello, world!”);

4. Второй пример программы

Сразу скажу, писать в качестве именно второго задания программу решения квадратного уравнения представляется чистой воды безумием. Отчасти и из-за использования вещественной арифметики. И уж тем более я надеюсь, никто в здравом уме не будет выписывать этот пример сразу же после предыдущего на том же занятии.

Собственно, критика автора относится к форматному вводу-выводу языка и отсутствия передачи параметров по ссылке. Да, на первом же занятии хотелось бы показать простейший ввод-вывод. Отлично, говорим, что scanf(“%d”, &a) считывает переменную целого типа, а printf(“%d”, a) выводит переменную целого типа на печать. В принципе, можно здесь и рассказать что %d – это есть «форматное преобразование», и что в printf можно вписывать произвольный текст. И этого достаточно, все, студенты уже готовы писать простейшие программы с вводом-выводом данных. Это не страшно, что у них, возможно, будут несколько printf или scanf подряд, puts будет использоваться для перехода на новую строку. Главное то, что начальный барьер для написания программ пройден.

Итак, барьер первой программы и простейшего ввода-вывода пройден. Что дальше?

5. Хак или не хак?

Стиль программирования, а именно, умение писать понятные и «красивые» программы, чем-то сродни литературному стилю. И то, и то невозможно привить без хорошего учителя и большой практики. И то, и то неформализуемо. Так и при изучении любого языка программирования студенты, будучи предоставленными самим себе, обычно склоняются к использованию «крутых» на их взгляд фич, естественно, в ущерб дисциплине и стилю программирования.

Дисциплину и стиль программирования необходимо внедрять железной рукой, пресекая в зародыше всякую самодеятельность студентов. Это начинается с фиксированного соглашения об оформлении программ (стиле кодирования), например как здесь. Программы нужно оформлять только так, как написано, любые отступления от стандарта караются отправлением задачи на доработку. Такая жесткость на самом деле очень быстро дает свои плоды.

Точно так же и стиль, явные нарушения стиля программирования должны караться отправлением задачи на доработку. Для того, чтобы стиль закрепился студенты должны решать много задач, а преподаватели просматривать все решения студентов. И это вполне достижимо технически и организационно, и делать это необходимо при обучении любому языку программирования, а не только языку Си.

Очевидным было бы заметить, что понятие «стиля» программирования и, как следствие, противоположное понятие «хак» весьма субъективны. Например, можно считать побочный эффект в заголовке цикла хаком, гнусно попирающим в угоду удобству светлые идеалы структурного программирования, а можно считать и наоборот, структурное программирование теоретической идеей, которая при фанатичном ей следовании приводит к плохочитаемым и плохосопровождаемым программам.


> Надо сразу отметить, что единственный более или менее адекватный времени семестр из этих четырех - третий, там где про Си и Unix.

Не очень понял значение "адекватный времени семестр".

И еще, что такое "кольцевой буфер"?

Кстати, обсуждая выбор языка программирования и подходов к обучению программированию, мы нашли очень много точек соприкосновения между твоим взглядом на преподавание программирования на ВМК и моим взглядом на преподавание программирования в матшколе.

Вот сейчас прочитав этот тест я нашел еще одну такую точку.

Когда я раньше планировал курс, то от Паскаля я тоже отказался, потому что это "мертвый язык". Я искал ему замену для "легкого старта", и в какой-то момент использовал для этого Питон... но в конечном счете победила логика, что результатом должно быть освоение C++, а поэтому тратить время на некоторый другой язык для первоначального обучения - бессмысленно. Лучше мы потратим время на преодоление барьера первоначального вхождения в C++. И я перестал использовать Питон.

Впрочем, тогда я рассматривал Питон не как полноценный язык, а как что-то игрушечное или учебное. Но это было семь лет тому назад... Сейчас я уже по-другому воспринимаю Питон, понимая, что на нем можно писать большие и полезные проекты, поэтому я уже считаю, что можно попробовать целиком заменить C++ на Питон у себя в школе.

Интересно было бы прочитать аналогичное эссе на тему "Замена С++ на Питон". :)

О некоторых аспектах и аргументах я догадываюсь, но из хотя из своё опыта предполагаю, что тех аспектов, о которых я не догадываюсь, куда больше.

По поводу Style Guide для студенческих программ идея очень крутая — даже жалко, что не все наши преподаватели выдвигают такие требования (хотя А.В. Ст., насколько я помню, тоже способствует развитию хорошего стиля программирования). Возможно, стоило бы снабдить его скриптом наподобие cpplint.py, чтобы другим было легче взять его на вооружение?

Да, конечно стоило бы. Осталось только такой скрипт написать :)

Под "Паскалем" последние лет двадцать все образованные люди, в отличие от Си-шных рептилоидов-технофошистов, имеют ввиду Оберон.

Это даже уже можно использовать как первый формальный признак образованности человека.

Дело в том, что Вирт, вместо того чтобы называть следующую версию своего языка "Паскалем Два", назвал его Модулой, затем Обероном. После "Оберона" он поддался общей моде и перестал менять название, а стал как и все просто добавлять номера к имени. Последняя на сегодняшний день версия Виртовского "Паскаля" называется "Оберон-07" (цифры 07 означают 2007 год).

Изучать Си первее Оберона = необратимо изуродовать мозг.

То что написал Андрей Столяров всем образованным людям известно уже 40 лет, поэтому и появился "Паскаль" -- "Оберон-07".
(Frozen) (Thread)

оставляю этот комментарий в качестве иллюстрации клинического немотивированного проявления агрессии со стороны кучки фанатиков-оберонистов.

Да, вынужден признать свою недостаточную образованность: я не знаю, что такое "фошист". Возможно, Вы хотели написать "фошыст"?

Комментарии к оригинальному комментарию и этому ответу будут удаляться.

Edited at 2010-02-04 11:04 am (UTC)
(Frozen) (Thread)

(Deleted comment)
Идея в том, что при соответственной организации курса "алгоритмы и алгоритмические языки" и практикума по курсу при использовании языка Си можно достичь результатов не хуже, чем с Паскалем.

В этом случае нет смысла тратить почти целый год на освоение Паскаля.

(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
Вы не учли, на мой взгляд, одну деталь: на Си-подобных языках программы пишутся быстрее, однако код читается хуже. На Паскале код читается объективно лучше, и сам он, соответственно, более понятен студентам. Недаром, ведь Русский Алгоритмический Язык, который разрабатывал в своё время Андрей Петрович Ершов (к слову разрабатывался он как раз таки для обучения) был так похож на "русскую" версию Паскаля.
(Frozen) (Thread)

Понятия "читаемости" и "понятности" являются субъективными и в большей мере зависят от стиля написания программы, нежели от языка.

Дальнейшее обсуждение этого вопроса здесь бесперспективно.
(Frozen) (Parent) (Thread)

// Стандартный паскаль - язык заведомо мертвый. Из популярных реализаций паскаля ни Borland Pascal, ни Free Pascal, ни Delphi даже и не пытаются этот стандарт поддерживать.

Тут-то Вы и прокололись.

Delphi вполне неплохо развивается. Особенно после того, как перешёл в руки Embarcadero. Так штаа...

Очевидно, Вы не поняли написанного.

Саша, здравствуйте, это Макс Лапшин, я у вас был в 2002-2003 учебном году.

Случайно попал на всю эту дискуссию, увидев вашу фамилию где-то в комментариях. Я за последние 6 лет много где успел поработать: больше сайтами занимался, но была и работа с видео (притом делали решения, которых ни у кого в мире больше нет), работал и в Гаранте с их базой данных, были и задачи связанные с большим потоком пользователей на сайте.

Я поработал с достаточно большим количеством людей и могу четко сказать, что практически все те из них, кто действительно квалифицированный программист, который не отступится перед проблемой со словами «тут что-то странное происходит», так вот почти все из них начинали с C или ассемблера.

Не выйдет хороший программист, да и алгоритмист из человека, у которого в «черной коробке» живут «волшебные гномики», которые его несчастного спасут от злых утечек памяти. Я по крайней мере не видел. Когда хорошо знаешь, что у всей этой индустрии под капотом, несравненно проще осваивать новые абстракции. Когда же база выстроена на высокоуровневых абстракциях, разорвать этот шаблон и спуститься вниз в тысячи раз сложнее, чем увидеть общность среди примитивных процессорных опкодов и поняться наверх.



Хочу отметить насчёт введения людей в курс дела и начала программирования. Каждый раз, когда я разбираюсь с новой технологией (будь то язык программирования, API или что-то ещё), всегда удобнее начинать с примеров, немного их модифицировать что бы почувствовать как оно работает, потом уже читать документацию и потом уже идти дальше. Эта фирменная ВМКшная фишка типа бросить человека сразу в самые жуткие теоретические дебри мне никогда не была понятна. Сначала жевать сопли полгода с паскалём переливая из пустого в порожнее, а потом сразу давать «программировать» на несуществующих компьютерах. Так, например, хоть какая-то связь между цепями Маркова, конечными автоматами и прочими вещами начинала появляться только на ваших занятиях по грамматикам.

Поэтому я конечно же считаю, что начинать надо всегда с готовых примеров, которые компилируются, запускаются и можно туда-сюда что-то поправить, что бы понять как писать. Очень, очень сложно когда знаешь что надо писать, но не понимаешь, как это сделать.


Что же до Столярова, то он может хоть исписаться, но в итоге спасибо вам, а ему лишь презрение от тех, кто выпустился.

Макс, рад Вас слышать.

Но просьба ни в коем случае не переходить к обсуждению личностей преподавателей.

Андрей в своей бескомпромисной манере выразил точку зрения многих очень уважемых преподавателей ВМК. И такая точка зрения вполне имеет право на существование.

Несмотря на то, что наши с Андреем точки зрения на многие вопросы диаметрально противоположны, это не убавляет моего к нему глубочайшего уважения. Он действительно один из лучших преподавателей, ведущих занятия на втором курсе.

Поддерживаю.

Стандартный Паскаль на первом семестре ВМК -- самое страшное воспоминание о программистских курсах. И если второй семестр в ассемблером и PDP-подобной УМ-3 имеет смысл, тупое заучивание методички про мертвый стандартный паскаль, бесило страшно.

Ну не мог я понять, почему должен учить язык, для которого не предлагалось даже интерпретатора. Turbo Pascal и Free Pascal имели существенные отличия, и не помня именно стандартного паскаля на тестировании можно было легко получить удовлетворительно.

Словом, поддерживаю вашу позицию. Жаль, не могу придумать, как мог бы помочь.

О чём я и говорил: если ориентироваться на тех, кто стал хорошими, высокооплачиваемыми программистами, то паскаль надо выкинуть. Если ориентироваться на остальных, то им бы всё программирование выкинуть =)

Было бы удивительно, если бы оказалось, что Андрей Викторович первым поднял эту проблему :)

Стэнфорд ввел Си вместо Паскаля в 1991 году. Их опыт описан здесь: http://j.mp/d4Xn8I. С другой стороны, в Беркли и MIT введение в программирование исслюстрируется кодом на Scheme. Учебник MIT'овского вступительного курса 6.001 я могу дать почитать, если интересно.

В общем-то выбор конкретного языка -- не повод для войны. Различия между C и Pascal (и даже Scheme -- в рамках начального курса) не настолько велики, чтобы списывать на них непонимание студентами концепции типов данных.

(на английском языке этот учебник доступен и онлайн: http://mitpress.mit.edu/sicp/full-text/book/book.html )

Вот я кстати не мог понять (и сейчас не могу), почему у меня на экзамене на пером курсе были вопросы вида "в стандарт Паскаля не входит" и дальше варианты ответа. Признаюсь, я на эти вопросы отвечал наобум, ибо не видел для себя никакого смысла заучивать мертвый и никому не нужный станадрт Паскаля. Я вообще отношусь скептически к заучиванию стандартов языков. Мне кажется, уверенное владение языком вырабатывается с опытом, а не с заучиванием документации. Стараясь написать программу как можно лучше и лакончинее приходиться обращаться к документации и более опытным коллегам, так и появляется уверенное владение.

А на тему организации курсов. Я бы украл программу Стенфорда или MIT %)

в связи с Вашим постом, хочется задать давно интересующий вопрос.

вот вы выступаете за автоматическое тестирование. в принципе, вполне нормальная идея - приучает к аккуратности, экономит всем массу времени.

но.

со слов многих студентов, часто возникает такая ситуация. написал программу, послал на тесты. не прошло. ну исправил все ошибки какие нашёл, подумал, ещё исправил, отправил на тесты. опять не прошло.

что делать дальше - непонятно. какие тесты программа не прошла - неизвестно. на что обратить внимание - никто не говорит. после того как студент постучался некоторое время головой об стенку и ничего придумать не смог, остаётся в общем-то два пути: либо забить на программу, либо списать у соседа.

в любом случае, обучения на ошибках не происходит. даже если списал у соседа, то может быть увидел правильную программу, но что было неправильно в своей может так и останется тайной за семью печатями.

собственно, вопрос в том - не следует ли что-то изменить в имеющейся системе, дабы обучение на своих ошибках всё-таки стало возможным.

Ну, для начала сформулируйте Ваши предложения.

Почему не преподавать подмножество языка С++ - проекцию элементов С++ на эдементы стандартного Паскаля? Например, передача параметра по ссылке в Паскале => передача параметра по ссылке в С++ (лишь текстуальное изменение "var" => "&"), т.е. снимается еще один контр-аргумент Столярова.

Я не считаю отсутствие ссылочных типов, якобы неправильные массивы и якобы неправильную модульность серьезным контр-аргументом.

Кроме того, преподавать некоторое подмножество языка Си++, выдавая его за "улучшенный" Си, мне кажется глубоко неправильным. Необходимо знать именно чистый Си и четко уметь отделять его от Си++.

Если Си и нуждается в каком-то улучшении, то это заведомо будут не ссылочные типы. Скажу даже больше, сама возможность передачи переменных простых типов (то есть не массивов и не структур) по ссылке, на мой взгляд, просто вредна при начальном обучении, да и вообще весьма сомнительна.

В частности, необходимость написания знака "&" перед переменной при передаче параметров уже привлекает внимание и заставляет задуматься, а может ли соответствующая переменная быть модифицирована в результате вызова.

Как человек, потративший изрядное количество времени на переработку плохо
написанного кода ("без #include" и с нарушением прототипов), очень желаю,
чтобы при преподавании программирования одновременно прививались какие-то
общепринятые стилевые навыки.

В частности, очень хотелось бы чаще встречать программистов, понимающих,
что упомянутая hello-world

#include <stdio.h>
int main() {
        printf("Hello, world\n");
        return 0;
}

приводит, грубо говоря, к следующему:

$ make -f bsd.prog.mk WARNS=5 PROG=hw MAN=
rm -f .gdbinit
touch .gdbinit
# compile tmp/hw.o
cc -O2 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wno-sign-compare -Wno-traditional -Wa,--fatal-warnings -Wreturn-type -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -Wextra -Wno-unused-parameter -Wsign-compare -std=gnu99 -Werror -c hw.c
cc1: warnings being treated as errors
hw.c:2: warning: function declaration isn't a prototype
*** Error code 1
Stop.
make: stopped in /tmp

Если кто-либо будет оспаривать, можно упомянуть, что этот подход принят
в таких проектах, как NetBSD. Практический выход - раннее обнаружение
проблем типа 2037-го года (и многих других тоже).

Кстати, этот же подход позволяет избежать вопросов, связанных с printf,
возможно, преподавателям надо лучше знать доступные инструменты,
тем более, что в переходе на уникс вы, как я понял, единодушны.

Я использую такие ключи и требую, чтобы компиляция проходила без ошибок.

gcc -O2 -Wall -Werror -Wformat-security -Wignored-qualifiers -Winit-self -Wswitch-default -Wfloat-equal -Wshadow -Wpointer-arith -Wtype-limits -Wempty-body -Wlogical-op -Wstrict-prototypes -Wold-style-declaration -Wold-style-definition -Wmissing-parameter-type -Wmissing-field-initializers -Wnested-externs -Wno-pointer-sign -std=gnu99