Директивы препроцессора

Когда мы видим #include <iostream>, это называется директивой препроцессора.

#include ---> директива

И я думаю:

<iostream> ---> препроцессор

Но что подразумевается под «препроцессором» и «директивой»?


person Simplicity    schedule 21.01.2011    source источник


Ответы (3)


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

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

РЕДАКТИРОВАТЬ, обращаясь к комментарию @ SWEngineer: многие люди считают полезным рассматривать препроцессор как отдельную программу, которая модифицирует программу C ++, а затем передает ее результат реальному компилятору C ++ (это в значительной степени то, что было раньше). Когда препроцессор видит #include <iostream>, он думает аааа - это то, что я понимаю, я собираюсь позаботиться об этом, а не просто передавать это вслепую компилятору C ++. Таким образом, он выполняет поиск в ряде каталогов (некоторые стандартные, такие как /usr/include и везде, где компилятор установил свои собственные заголовки, а также другие, указанные с помощью -I в командной строке) в поисках файла с именем iostream. Когда он его находит, он затем заменяет строку во входной программе с #include полным содержимым файла с именем iostream, добавляя результат к выходным. НО, затем он переходит к первой строке, которую он прочитал из файла iostream, ища другие директивы, которые он понимает.

Итак, препроцессор очень простой. Он может понимать #include, #define, _6 _ / _ 7 _ / _ 8_, #ifdef и $ifndef, #warning и #error, но не более того. Он не имеет ни малейшего понятия, что такое int, шаблон, класс или что-то из этого реального C ++. Это больше похоже на некий автоматический редактор, который вырезает и вставляет части файлов и кода, подготавливая программу, которую компилятор C ++ в конечном итоге увидит и обработает. Препроцессор по-прежнему очень полезен, потому что он знает, как находить части программы во всех этих разных каталогах (на следующем этапе компиляции ничего не нужно знать об этом), и он может удалить код, который может работать на каком-то другом. компьютерная система, но не будет действительна для той, которая используется. Это также может позволить программе использовать короткие краткие операторы макросов, которые генерируют большой объем реального кода C ++, что делает программу более управляемой.

person Tony Delroy    schedule 21.01.2011
comment
@Тони. Можете ли вы просто объяснить это, например, с помощью #include ‹iostream›? Так как я почти понял. Спасибо. - person Simplicity; 21.01.2011
comment
@Тони. (директивы препроцессора - это указания препроцессору об изменениях, которые он должен внести в код до того, как начнутся более поздние этапы компиляции). Какие здесь примеры изменений? Спасибо. - person Simplicity; 21.01.2011
comment
@Тони. Извините за мои многочисленные вопросы. Что касается препроцессора, не могли бы вы описать его поподробнее? Спасибо. - person Simplicity; 21.01.2011
comment
@SWEngineer: Я попытался объяснить немного лучше выше. Надеюсь, это поможет. Но мне нужно еще куда-нибудь побывать - могу не проверять онлайн часами или днями ... извините. Надеюсь, этого достаточно. - person Tony Delroy; 21.01.2011
comment
@Тони. Большое спасибо за ваше хорошее объяснение, очень признателен. Просто мелочь, когда найдешь когда-нибудь. Когда вы говорите: НО, он переходит к первой строке, которую прочитал из файла iostream, ища другие понятные ему директивы .. А как насчет других директив препроцессора в файле .cpp, которые нужно скомпилировать и запустить? Большое спасибо. - person Simplicity; 21.01.2011
comment
@SWEngineer: Помните, я сказал, что он вставляет iostream вместо строки #include ‹iostream›? Таким образом, он затем обрабатывает строки, поступившие из iostream, но исходные строки из файла, содержащего этот оператор include, все еще продолжаются. Вы можете сказать, что он позволяет отвлекаться на содержимое файла iostream, но не забывает вернуться к тому, что делал заранее. - person Tony Delroy; 23.01.2011
comment
Приведем повседневный пример: представьте, что вы читаете книгу, но всякий раз, когда вы находите что-то интересное, вы хотите найти более подробную информацию в книге, специализирующейся на этой теме. Итак, вы кладете первую книгу корешком вниз, но при этом открываете страницу, которую читаете. Если после этого вы читаете вторую книгу и обнаруживаете в ней что-то интересное, вы кладете ее корешком поверх предыдущей книги, открываете там страницу, которую читаете, и берете еще одну книгу. По мере того, как вы завершаете дополнительное исследование, не находя нового интересного, вы закрываете книги и берете более ранние ... - person Tony Delroy; 23.01.2011
comment
в конце концов, вы дойдете до того, что дочитали первую книгу. Программа на C ++ немного похожа на эту в том смысле, что она включает в себя материалы из других файлов, и они могут включать в себя и другие файлы: все это образует своего рода дерево, в котором один файл может разветвляться, включая множество других, и каждая ветвь может ветвиться снова, но, в конце концов, вы втягиваете все ветки, и получается полная единица перевода (достаточно C ++ для создания одного объекта, это может быть библиотека, программа или что-то готовое для связывания для формирования программы). - person Tony Delroy; 23.01.2011

#include - это директива препроцессора, <iostream> - это просто аргумент, поставляемый в дополнение к этой директиве, которая в данном случае является именем файла.

Некоторые директивы препроцессора принимают аргументы, некоторые - нет, например

#define FOO 1

#ifdef _NDEBUG
    ....
#else
    ....
#endif

#warning Untested code !

Общей чертой является то, что все они начинаются с #.

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

person Paul R    schedule 21.01.2011

Директивы препроцессора, такие как #define и #ifdef, обычно используются для упрощения изменения исходных программ и их компиляции в различных средах выполнения. Директивы в исходном файле предписывают препроцессору выполнять определенные действия. Например, препроцессор может заменять токены в тексте, вставлять в исходный файл содержимое других файлов ...

#include - это директива препроцессора, означающая, что она используется частью компилятора препроцессором. Это происходит «до» компиляции. #include необходимо указать, что включать, это предоставляется аргументом iostream. Это указывает препроцессору включить файл iostream.h.

Дополнительная информация:

person Devendra D. Chavan    schedule 21.01.2011
comment
В #include необходимо указать, что нужно включить, это предоставляется аргументом iostream. Это указывает препроцессору включить файл iostream.h. Нет, это не так. Он сообщает препроцессору, что нужно включить файл iostream. - person Lightness Races in Orbit; 21.09.2011