Где именно находится граница между препроцессором и компилятором? - PullRequest
8 голосов
/ 25 августа 2011

Согласно различным источникам (например, радиоэпизод SE с Кевлином Хенни , если я правильно помню), "C с классами" был реализован с использованием технологии препроцессора (с выходом, который затем подается наКомпилятор C), в то время как C ++ всегда был реализован с помощью компилятора (который просто выплевывал C в первые дни).Кажется, это вызывает некоторую путаницу, поэтому мне было интересно:

Где именно находится граница между препроцессором и компилятором?Когда вы называете часть программного обеспечения, которая реализует язык «препроцессор», и когда вы называете его «компилятором»?

Кстати, является ли «скомпилированный язык» установленным термином?Если так, что именно это означает?

Ответы [ 6 ]

8 голосов
/ 25 августа 2011

Это интересный вопрос.Я не знаю однозначного ответа, но скажу следующее, если нажать одну из них:

Препроцессор не анализирует код, а вместо этого сканирует встроенные шаблоны и расширяет их

Компилятор фактически анализирует код путем построения AST (абстрактного синтаксического дерева) и затем преобразует его в другой язык

4 голосов
/ 25 августа 2011

Язык вывода препроцессора является подмножеством языка ввода.

Язык вывода компилятора (обычно) сильно отличается (машинный код) от языка интерфейсавход.

2 голосов
/ 25 августа 2011

Компилятор C / C ++ заботится о корректности типов , в то время как препроцессор просто расширяет символы.

2 голосов
/ 25 августа 2011

С упрощенной, личной, точки зрения:

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

Компилятор запускается, когда к обрабатываемому объекту применяются правила и правила (да, это делает «мой» препроцессор компилятором, но почему бы и нет: P),это включает в себя симметричную и лексическую проверку, и включенные преобразования преобразуются из x (текстовой) в y (двоичной / промежуточной формы).как сказал бы один из моих профессоров: «это система с входами, процессами и выходами».

0 голосов
/ 03 сентября 2011

Ответ довольно прост.Препроцессор работает с текстом в качестве входных данных и имеет текст в качестве выходных данных.Примерами этого являются старые unix-команды m4, cpp (предварительный процессор C), а также unix-программы, такие как roff и nroff и troff, которые использовались (и остаются) для форматирования man-страниц (unix-команда «man») или форматирования текста.для печати или набора текста.Препроцессоры очень просты, они ничего не знают о «языке текста», который они обрабатывают.Другими словами, они обычно обрабатывают естественные языки.Препроцессор C помимо своего имени, например, распознает только #define, #include, #ifdef, #ifndef, #else и т. Д., И если вы используете #define MACRO, он пытается «развернуть» этот макрос везде, где он его находит.Но это не обязательно должен быть программный текст на C или C ++, это также может быть роман, написанный на итальянском или греческом.Компиляторы, которые пересекают компиляцию на другой язык, обычно называют переводчиками.Таким образом, старый «компилятор» cfront для C ++, который генерировал код C, был переводчиком C ++.Препроцессоры и более поздние переводчики использовались исторически, потому что старым машинам просто не хватало памяти, чтобы сделать все в одной программе, а вместо этого это делали специализированные программы и с диска на диск.Типичная программа на С будет составлена ​​из различных источников.И процесс сборки будет управляться с помощью make .В наши дни препроцессор C обычно встроен непосредственно в компилятор C / C ++.Типичный запуск make вызывает CPP для файлов * .c и записывает вывод в другой каталог, откуда либо компилятор C C компилирует его прямо в машинный код, либо чаще выводит код ассемблера в виде текста.Примечание: компилятор c проверяет только синтаксис, на самом деле он не заботится о безопасности типов и т. Д. Затем ассемблер берет этот код ассемблера и выводит файл * .o, который позже может быть связан с другими файлами * .o и * .lib.файлы в исполняемую программу.OTOH, скорее всего, у вас есть правило make, которое не вызывает компилятор C, а команду lint, анализатор языка C, которая ищет типичные ошибки и ошибки (которые игнорируются компилятором c).Довольно интересно посмотреть на lint, nroff, troff, m4 и т. Д. В Википедии (или на терминале вашей машины, использующем man); D

0 голосов
/ 25 августа 2011

Компилятор состоит из сервальных процессов (компонентов). Препроцессор - только один из них и относительно самый простой.

Из статьи в Википедии Разделение процессов компилятора :

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

Обычно считается, что синтаксический интерфейс и семантическая обработка происходит вместе с переводом на более низкий уровень представления (чем исходный код).

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

Бэкэнд берет вывод из середины. Это может выполнить больше анализ, преобразования и оптимизации, которые предназначены для конкретного компьютер. Затем он генерирует код для конкретного процессора и ОС. "

Предварительная обработка - это только малая часть работы переднего плана.

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

В настоящее время я не думаю, что такой неродной компилятор C ++ может выжить в коммерческой сфере.

Смею сказать, cfront для C++11 невозможно сделать.

...