Какую часть компилятора мы должны знать?

Для того, чтобы написать лучший код, стоит ли глубоко знать, что делает компилятор?

Как много будет достаточно? Я не немного скруббер, но я думал, что знание того, как работает компилятор, сделает меня лучшим программистом. Я ошибся?

Если да, какие ресурсы вы бы порекомендовали?

13 ответов

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

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

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

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


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


Edit2: Многие из обычных текстов используют довольно абстрактный, математический подход к проблеме компилятора, который поначалу может пугать или сбивать с толку. Учебное пособие Crenshaw основано на подходе "начать разбивать код", основанном на более тонком понимании автора. Хорошее вступление, но если вы серьезны, вам следует провести более формальное исследование.

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

  1. Если вы не имеете ни малейшего представления о том, что делает компилятор, вы можете непреднамеренно написать код, который намного дороже, чем вы предполагали. Это особенно верно, если вы выделяете память, не зная об этом. Классическим примером является объединение строк в цикле, например, как в

    ответ = ""

    для я = 1 до п сделать

      answer = answer .. strings[i]    -- .. is string concatenation
    

    Этот код является квадратичным, выполняя квадратичное количество выделения и копирования. Плохие новости.

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

Учебник Креншоу не плохой. Еще одна приятная книга, если вы можете взять ее в руки, это книга П.Дж. Брауна об интерактивных компиляторах и интерпретаторах. Он давно распечатан, но вы можете найти его в библиотеке.

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

Я думаю, что это, безусловно, сделает вас лучшим программистом.

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

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

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

Вы заинтересованы в эффективном использовании отладчика? Тогда да. Вы заинтересованы в написании надежного или эффективного кода? Тогда да.

Лично я забочусь о бэкэнде больше, чем о фронтэнде. Я рекомендую компилировать для ARM вместо x86, в этом случае вы не обязательно изучаете ассемблер (где я рекомендую написать свой собственный дизассемблер), поэтому, если вы используете gcc, у него есть дизассемблер, и вы можете увидеть, что ваш код высокого уровня делает для изменения конечный результат, а также сколько изменений вы можете сделать с помощью параметров компилятора. Большинству программистов на языке высокого уровня понятно, что один и тот же код может иметь совершенно разные результаты в зависимости от используемых параметров компилятора и командной строки.

Для середины компилятора я рекомендую как lcc, так и sdcc. Вы можете или не можете купить LCC книгу:

[ http://www.cs.princeton.edu/software/lcc/][1]

Вам не нужно, хотя, источник находится в сети (во многих формах). Как и sdcc (небольшой компилятор устройства c, созданный первоначально для 8051 и других 8-битных микро). Я рекомендую зайти в интерфейс, где компилятор отвечает бэкэнду, вы обнаружите, что ваш код превращен в серию атомарных частей, иногда наоборот. а = б + 7; может закончиться тем, что загрузит постоянное целое число 7. читает из памяти переменную b в следующие доступные регистры. Добавьте 7 плюс регистр с помощью b и сохраните в следующем доступном регистре. сохранить значение в регистре в месте в памяти для.

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

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

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

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

Со временем вы научитесь не слишком стараться писать для компилятора. Просто не тратьте впустую свой код, не пользуйтесь особенностями языка. Если вам нужно было провести дополнительное исследование, чтобы выяснить какую-то особенность компилятора, вы можете быть уверены, что большая часть мира не понимает этого, включая человека, который должен реализовать его в компиляторах. Поэтому вы можете ожидать, что эта функция не будет работать согласованно между компиляторами, поэтому вы должны использовать ее в первую очередь. Это также означает, что не пытайтесь писать свой код для одного конкретного компилятора, не слишком привязывайтесь к gcc и его функциям, пробуйте sdcc и lcc, а также microsoft, borland, kiel и другие. Сделайте ваш код чистым, простым, читаемым и переносимым.

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

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

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

РЕДАКТИРОВАТЬ

Например: компиляторы C хранят данные в массивах в основном формате строк, поэтому вам следует перебирать многомерные массивы, варьируя сначала самое высокое измерение (самый правый индекс), а затем переходя к самому низкому измерению (самый левый индекс). Fortran делает с точностью до наоборот, сохраняя массивы в основном формате столбцов. Это означает, что в Фортране вы должны сначала изменить самое низкое измерение, переходя к самому высокому измерению. Это улучшит коэффициент попадания в кэш вашего кода и значительно улучшит производительность для больших многомерных массивов.

В своем блоге Стив Йегге заявил, что все программисты должны знать, как работают компиляторы. Он заходит так далеко, что говорит:

Нежное, но настойчивое резюме: если вы не знаете, как работают компиляторы, вы не знаете, как работают компьютеры. Если вы не уверены на 100%, знаете ли вы, как работают компиляторы, вы не знаете, как они работают.

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

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

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

Не учите компиляторы, изучайте решаемые ими проблемы.

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

Если вам интересно, я бы порекомендовал приобрести Книгу Дракона, также известную как Компиляторы: Принципы, Методы и Инструменты. Это может быть немного тяжело в первый раз, но это, безусловно, заставит вас задуматься. Если вы не пройдете весь путь до конца или не застрянете в некоторых частях, я бы посоветовал отложить его на некоторое время и вернуться позже - гораздо легче пройти через второй раз.

Я думаю, что то, что делает компилятор, является здесь важной вещью (он создает объяснение с характеристиками x,y,z), что переводится в знание платформы, на которую вы ориентируетесь.

То, как она выполняет эту задачу, не имеет значения (если, конечно, вы не пишете компиляторы)

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

:) Кажется очевидным, но я удивлен количеством встреченных мной разработчиков, которые даже не смотрели на результаты компиляции.

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

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

Я думаю, что на самом деле очень важно сделать переводчика: он дает вам более глубокое понимание языков программирования, и это то, что вы используете... В схеме на самом деле сложно создать интерпретатор! Но на самом деле я бы очень рекомендовал читать части SICP для лучшего освещения).

Что касается компиляторов, это более сложно, так как в центре внимания здесь получить некоторую производительность / делать это для реальной машины. Как программист, важно знать, по крайней мере, какие задачи они выполняют глобально и когда они выполняются, а не детали, потому что в настоящее время они превратились в действительно сложные системы, особенно с JIT и т. Д.

Другие вопросы по тегам