Урок 3 (С/С++)
Два слова вначале: у группы, пишушей уроки С/С++ возникли некоторые разногласия по поводу данного урока. А конкретнее- его своевременности и доступности. В конечном итоге, предлагаю сделать так: посмотрите этот урок, если вам он покажется сложным, не вникайте глубоко, впоследствии мы еще вернемся к нему. Если же вы нормально его воспримете- тем лучше. Я, собственно, согласна с тем, что возможно и не стоило его вставлять в начало курса, но я исходила из того, что при написании первой программы хотя бы приблизительно хочется знать, а в чем смысл непонятных, но многочисленных строк. Я все-таки рискнула дать этот материал сейчас.

Среда Borland C++ 3.1 и этапы выполнения программы на С/С++. Познакомимся со средой, в которой будем работать (Borland C++ 3.1). При запуске программы вы увидите меню. С пунктами меню будем знакомиться по мере надобности. Для начала рассмотрим пункт меню File. New- создает новый файл. Open - открывает уже существующий файл в текущем каталоге. Если файл, который нужно открыть, лежит в другом каталоге, нужно будет воспользоваться командой Change dir.

Save, Save as, Save all- команды сохранения файла. Первые две должны быть вам знакомы по другим программам (Word, например), а третья будет сохранять все файлы, открытые в данный момент в вашем Borland C++ 3.1. Quit- выход. Открываете файл и начинаете набирать код. Но это несколько позже.Сейчас познакомимся с процессами, происходящими при написании программы от набора первого символа до запуска. Для того, чтобы выполнить программу, нужно пройти 6 этапов:

1. Редактирование.
Это этап набора кода в редакторе программ. В нашем случае это будет открывшееся окно, прямо в котором можно набирать код. Этот этап называется редактированием, потому что вы можете исправить часть кода, если необходимо, запомнить его непроверенным или недописанным до конца. На этом этапе вы работаете с кодом как с простым текстом. Файлы, сохраненные с возможностью их редактирования имеют расширение .cpp, .cxx, .C (заглавная буква) или .с в зависимости от используемой среды программирования. В случае Borland C++ 3.1 мы будем получать файлы с расширением .cpp.

2. Работа препроцессора.
Прежде чем программа сможет начать выполнение, код, написанный вами, должен быть переведен в машинный код (вспоминайте урок 1), то есть, откомпилирован. Вы даете команду компилировать программу, но перед компиляцией происходит предварительная обработка вашей программы - это работа препроцессора. Она заключается в том, что перед компиляцией необходимо выполнить определенные преобразования в вашей программе. Какие? Это зависит от специальных команд, которые называются командами препроцессора или директивами препроцессора. Все (!) директивы препроцессора начинаются с символа # При выборе команды компиляции вашего файла в первую очередь идет анализ текста на наличие этого знака. Таким образом распознаются команды для работы препроцессора. Что же он должен делать? Препроцессор вставляет в ваш код участки текста или полностью текст других программных файлов, которые необходимы для нормальной правильной компиляции вашей программы. Например, директива #include подключает текст файла к вашей программе. Если вы пишете #include "file1.h" - это значит, что в текст того файла, где вы написали данную строчку, на ее место вставится весь текст файла, у которого имя file1.h.

Комментарий Сашка 1. В языках С и С++ существует стандартная корневая директория для файлов-заголовков. Она может различаться в зависимости от компилятора. Например, для Turbo C/C++ это по умолчанию

...TCINCLUDE,
где ТС - директория, в которую установлен ТС.

Для Unix'a это будет стандартная директория /usr/include. При использовании команды препроцессора #include <iostream.h>, он ищет указанный файл-заголовок (iostream.h) именно в этой директории. Более того, путь для команды #include<...> тоже указывается относительно нее. То есть, если написано #include<sys/stat.h> или #include<sysstat.h>, препроцессор будет искать файл /usr/include/sys/stat.h (Unix), или ...TCINCLUDEsysstat.h (Turbo C/C++) соответственно.

Описанное поведение удобно до тех пор, пока мы пользуемся только стандартными файлами-заголовками. Однако, как только мы начинаем создавать свои собственные - возникают проблемы: помещать файлы-заголовки, относящиеся только к одному проекту, в стандартные директории чревато путаницей в дальнейшем, когда проектов будет несколько. Поэтому, существует еще один вид синтаксиса:
#include "myheader.h".
В этом случае препроцессор сначала ищет файл myheader.h в рамках директории нашего проекта и лишь потом, не найдя его там - в стандартной директории. Естественно, для работы с поддиректориями, как и в первом случае, указывается относительный путь.

#include <iostream.h>
- такая строка будет означать, что вы подключили к вашему файлу (вставили в него) стандартный библиотечный файл. В некоторых редакторах кода С++ при подключении такого файла вы не должны будете писать расширение, а только #include <iostream>. Почему - читайте комментарий 2.


Комментарий Сашка 2.
Разница между iostream и iostream.h состоит в использовании namespace. Основная идея понятия namespace - разрешить конфликты, связанные с неуникальностью имен в больших проектах. При наличии namespace связанные между собой по смыслу части объединяются в рамках одного и того же namespace, в то время, как разные по смыслу части находятся в разных. В рамках одного и того же namespace к имени функции (класса, переменной) можно обращаться непосредственно, из другого namespace надо применять полное имя, включающее имя namespace, :: и имя функции (класса, переменной). Не думаю, что здесь имеет смысл описывать детально синтаксис namespace, но один момент надо подчеркнуть: использование команды using namespace aaa; приведет к тому, что в дальнейшем все, содержимое namespace ааа будет рассматриваться как "свое", не требующее применения полного имени.

Понятие namespace было добавлено в С++ где-то в середине 90-х. Это привело к несовместимости со старыми файлами-заголовками. Для того, чтобы можно было продолжать использовать как новый стиль, так и старый стиль (в том числе и С, а не только С++), существуют 2 комплекта стандартных файлов-заголовков:
Язык С namespace Без namespace
C++
шаблон: xxxxx
примеры: iostream, iomanip

xxxxx.h
iostream.h, iomanip.h

C
шаблон: cyyyyy
примеры: cstdio, cstdlib

yyyyy.h
stdio.h, stdlib.h

Как видим, программы с namespace ( using namespace std; ) должны использовать iostream, без него - iostream.h. В связи с тем, что в ранних версиях С++ namespace не было, там использовалось только iostream.h.

#define pi 3.14 - эта строка означает, что везде в вашей программе, в местах, где вы поставите слово pi, препроцессор произведет замену его на текст 3.14, который, естественно, будет восприниматься компилятором как число.

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

3. Этап компиляции.
На этом этапе выполняется во-первых, проверка текста на ошибки (здесь проверяются только ошибки синтаксиса языка на котором вы писали - ошибки в работе самой программы выявляются при ее тестировании); во-вторых, перевод исходного кода, уже включающего в себя подстановки препроцессора в машинный код. Создается файл с расширением .obj, так называемый- объектный файл. Во многих местах вашей программы, когда вы пишете код, вы используете вызов уже готового кода, хранящегося в тех или иных библиотеках. Так вот - в объектном файле эти ссылки на библиотеки еще не работают. Библиотеки еще не подключены. Говорят, что такой файл не обладает функциональностью.

4. Этап компоновки.
На этом этапе все ссылки на библиотеки заменяются конкретными участками кода из этих библиотек, появляется функциональность кода. После этого создается загрузочный модуль. Для Windows его расширение будет .exe, для Unix .out

Комментарий Сашка 3. Unix сам по себе не
использует понятие "расширение" для имени файла. Исторически это связано с тем, что МС ДОС отводил слишком мало места для имени, а Unix с самого начала этим недостатком не страдал, и потому расширять имя не надо было. Что же касается ".out", то в Unixе просто создается по умолчанию исполняемый файл "a.out" и никакой другой при компиляции С/С++. Это очень неудобно, поэтому все пользуются флагом "-o", позволяющим задать любое имя файла. В отличие от Windows (MS DOS), для которых исполняемый файл должен иметь расширение .ехе или .сом, Unixу вообще все равно, как выглядит имя исполняемого файла.

5. Этап загрузки.
Перед выполнением программа должна быть размещена в оперативной памяти. На данном этапе исполняемый загрузочный модуль считывается с диска и загружается в оперативную память.

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

Автор: Never и Sashok
Information
  • Posted on 31.01.2010 20:41
  • Просмотры: 381