Каждая программа на языке С есть последовательность препроцессорных директив, описаний и определений глобальных объектов и функций. Препроцессорные директивы управляют преобразованием текста программы до ее компиляции. Определения и описания программы на языке Си могут размещаться в строках текстового файла достаточно произвольно (в свободном формате.) Для препроцессорных директив существуют ограничения. Во-первых, препроцессорная директива обычно размещается в одной строке, т.е. признаком ее окончания является признак конца строки текста программы. Во-вторых, символ ‘#’, вводящий каждую директиву препроцессора, должен быть первым отличным от пробела символом в строке с препроцессорной директивой.
Исходная программа, подготовленная на языке Си в виде текстового файла, проходит три обязательных этапа обработки:
• препроцессорное преобразование текста;
• компоновка (редактирование связей или сборка).
Только после успешного завершения всех перечисленных этапов формируется исполняемый машинный код программы.
Этапы компиляции на Си: предобработка, трансляция, компоновка
Задача препроцессора – преобразование текста программы до ее компиляции. Правила препроцессорной обработки определяет программист с помощью директив препроцессора. Каждая препроцессорная директива начинается с символа ‘#’. В этой работе нам будет достаточно двух директив: #include и #define.
Препроцессорная директива #defineуказывает правила замены в тексте. Директива #includeопределяет, какие текстовые файлы нужно включить в этом месте текста программы.
Директива #include предназначена для включения в текст программы текста файла из каталога заголовочных файлов, поставляемых вместе со стандартными библиотеками компилятора
Препроцессорная обработка выполняется на уровне исходного текста программы. Директива #include только позволяет вставить в текст программы описания из указанного заголовочного файла. Подключение к программе кодов библиотечных функций осуществляется только на этапе редактирования связей (этап компоновки), т.е. после компиляции, когда уже получен машинный код программы.
После выполнения препроцессорной обработки в тексте программы не остается ни одной препроцессорной директивы.
Теперь программа представляет собой набор описаний и определений. Если не рассматривать определений глобальных объектов и описаний, то программа будет набором определений функций.
Среди этих функций всегда должна присутствовать функция с фиксированным именем main.Именно эта функция является главной функцией программы, без которой программа не может быть выполнена. Имя этой главной функции для всех программ одинаково (всегда main)и не может выбираться произвольно.
Стандартные файлы и функции для работы с ними.
Потоки – это наиболее удобные средства для чтения или записи данных в файл в С. Они позволяют разрабатывать гибкий и эффективный ввод/вывод, который не зависит от используемых файлов или встроенного оборудования.
Поток является файлом или физическим устройством (принтером или монитором, например), которым вы управляете с помощью указателей на объект FILE (определенный в stdio.h). Объект FILE содержит различную информацию о потоке, включая текущую позицию потока, указатели на соответствующие буферы и индикаторы ошибки или конца файла.
Работа с файлами с++. Запись в файл. c++ ofstream. Изучение С++ для начинающих. Урок #115
Функция открытия потока выглядит следующим образом:
Для контроля открытия потока следует воспользоваться нижеприведенной конструкцией:
if ((fp = fopen(*имя_файла, *режим)) = = NULL)
fprintf(stderr, «Cannot open input file.n»);
После того как файл открыт, с ним можно работать, записывая в него информацию или считывая ее (в зависимости от режима).
Открытые на диске файлы после окончания работы с ними рекомендуется закрыть явно. Для этого используется библиотечная функция int fclose(FILE *fp);
Открытый файл можно открыть повторно только после того, как файл будет закрыт с помощью функции fclose().
Для работы с файлами на диске предусмотрены функции:
fgetc(), fputc(), fprintf(), fscanf(), fgets(), fputs(), fseek(), ftell(), fwrite().
Источник: www.megapredmet.ru
Структура программы на Си
Директивы препроцессора управляют преобразованием текста программы до ее компиляции. Исходная программа, подготовленная на Си в виде текстового файла, проходит 3 этапа обработки:
1) препроцессорное преобразование текста;
3) компоновка (редактирование связей или сборка).
После этих трех этапов формируется исполняемый код программы. Задача препроцессора – преобразование текста программы до ее компиляции. Правила препроцессорной обработки определяет программист с помощью директив препроцессора. Директива начинается с #. Например,
1) #define – указывает правила замены в тексте.
#define ZERO 0.0 – означает, что каждое использование в программе имени ZERO будет заменяться на 0.0.
2) #include – предназначена для включения в текст программы заголовочных файлов, поставляемых вместе со стандартными библиотеками. Каждая библиотечная функция Си имеет соответствующее описание в одном из заголовочных файлов. Список стандартных заголовочных файлов определен стандартом языка.
Употребление директивы include не подключает соответствующую стандартную библиотеку, а только позволяет вставить в текст программы описания из указанного заголовочного файла. Подключение кодов библиотеки осуществляется на этапе компоновки, т.е. после компиляции. Хотя в заголовочных файлах содержатся все описания стандартных функций, в код программы включаются только те функции, которые используются в программе.
После выполнения препроцессорной обработки в тексте программы не остается ни одной препроцессорной директивы.
Некоторые заголовочные файлы:
· ALLOC.H – функции для работы с памятью
· CONIO.H – функции консольного ввода-вывода
· DIR.H – работа с файлами и каталогами
· IO.H – функции для работы с файлами
· IOSTREAM.H – библиотека Си++ потоков ввода/вывода
· COMPLEX.H, MATH.H – математические функции
· STDIO.H – стандартная библиотека ввода-вывода
· STDLIB.H – библиотека стандартных функций
· STRING.H – функции для работы со строками
· TIME.H – функции для работы с датой и временем
Программа представляет собой набор описаний и определений и состоит из набора функций. Функции – это строительные блоки языка, самостоятельные единицы программы, спроектированные для решения конкретных задач. Обычно функции в программе повторяются несколько раз. Среди функций всегда должна быть функция с именем main. Без нее программа не может быть выполнена.
Особенностью стандарта языка Си является то, что для создания правильного машинного кода функции ему необходимо сообщить до ее первого вызова тип возвращаемого результата, а также количество и типы аргументов. Для этой цели используется понятие прототипа функции, который задается следующим образом:
тип (список параметров);
Перед именем функции помещаются сведения о типе возвращаемого функцией значения (тип результата). Если функция ничего не возвращает, то указывается тип void. Вы не обязаны объявлять функцию типа void, это не будет препятствием для компиляции, однако объявление типа возвращаемого значения функции является хорошим правилом. Каждая функция, в том числе и main, должна иметь набор параметров, он может быть пустым, тогда в скобках указывается (void).
После определения прототипа размещаются заголовок и тело функции. Чаще всего заголовок функции совпадает с ее прототипом. Тело функции – это последовательность определений, описаний и исполняемых операторов, заключенных в фигурные скобки. Определения, описания и операторы заканчиваются точкой с запятой. После фигурных скобок точка с запятой не ставится.
Определения вводят объекты (объект – это именованная область памяти, частный случай объекта – переменная), необходимые для представления в программе обрабатываемых данных. Примерами являются:
Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:
Источник: studopedia.ru
Этапы обработки программы от исходного кода к исполняемому в операционных системах
Цель работы: ознакомиться с последовательностью обработки программы от исходного кода к исполняемому в операционных системах на примере языка С++.
Индивидуальное задание
Провести анализ этапов обработки программы от исходного кода к исполняемому в операционных системах.
Оборудование: ПК с операционной системой Windows XP/7/8.
Теоретические сведения
Объединенная единым алгоритмом совокупность описаний и операторов образует программу на алгоритмическом языке. Для того чтобы выполнить программу, требуется перевести ее на язык, понятный процессору — в машинные коды. Этот процесс состоит из нескольких этапов. Рисунок ниже иллюстрирует эти этапы для языка С++.
Сначала программа передается препроцессору, который выполняет директивы, содержащиеся в ее тексте (например, включение в текст так называемых заголовочных файлов — текстовых файлов, в которых содержатся описания используемых в программе элементов).
Получившийся полный текст программы поступает на вход компилятора, который выделяет лексемы, а затем на основе грамматики языка распознает выражения и операторы, построенные из этих лексем. При этом компилятор выявляет синтаксические ошибки и в случае их отсутствия строит объектный модуль.
Компоновщик, или редактор связей, формирует исполняемый модуль программы, подключая к объектному модулю другие объектные модули, в том числе содержащие функции библиотек, обращение к которым содержится в любой программе (например, для осуществления вывода на экран). Если программа состоит из нескольких исходных файлов, они компилируются по отдельности и объединяются на этапе компоновки. Исполняемый модуль имеет расширение.ехе и запускается на выполнение обычным образом.
Таким образом создаются исполняемые программы на C++. Конечно это очень общее описание этого сложного процесса, но четко передает смысл всех этапов работы компилятора и компоновщика.
оздание исполняемого файла издавна производилось в три этапа: (1) обработка исходного кода препроцессором, (2) компиляция в объектный код и (3) компоновка объектных модулей, включая модули из объектных библиотек, в исполняемый файл. Это классическая схема для компилируемых языков. (Сейчас уже используются и другие схемы.)
Часто компиляцией программы называют весь процесс преобразования исходного кода в исполняемы модуль. Что неправильно. Обратите внимание, что в IDE этот процесс называется построение (build) проекта.
IDE обычно скрывают три отдельных этапа создания исполняемого модуля. Они проявляются только в тех случаях, когда на этапе препроцессинга или компоновки обнаруживаются ошибки.
Итак, допустим, у нас есть программа на C++ «Hello, World!»:
Сначала исходный код обрабатывается препроцессором. Препроцессор находит директиву #include, ищет файл iostream и заменяет директиву текстом из этого файла, попутно обрабатывая все директивы препроцессора во включаемом тексте.
Файл, указанный в директиве #include, в данном случае является заголовочным файлом (или «хеадером», «хидером», «заголовком»). Это обычный текстовый файл, содержащий объявления (объявления типов, прототипы функций, шаблоны, директивы препроцессора и т.п.). После текстуального включения заголовочного файла в текст программы (или модуля) становится возможным использование в тексте программы всего того, что описано в этом заголовочном файле.
Затем результат работы препроцессора передаётся компилятору. Компилятор производит весь положенный комплекс работ: от синтаксического разбора и поиска ошибок до создания объектного файла (понятно, что если имеются синтаксические ошибки, то объектный файл не создаётся). В объектном файле обычно имеется таблица внешних ссылок — некая таблица, в которой, в частности, перечислены имена подпрограмм, которые используются в объектном модуле, но код которых отсутствует в данном объектном модуле. Эти подпрограммы внешние по отношению к модулю.
Исходный код, который может быть откомпилирован, называется единицей компиляции. Наша программа содержит одну единицу компиляции.
Что бы получить нормальный исполняемый модуль, необходимо «разрешить» внешние ссылки. Т.е. добавить в исполняемый модуль код отсутствующих подпрограмм и настроить соответствующим образом все ссылки на этот код. Этим занимается компоновщик. Он анализирует таблицу внешних ссылок объектного модуля, ищет в объектных библиотеках недостающие модули, копирует их в исполняемый модуль и настраивает ссылки. После этого исполняемый модуль готов.
Библиотека (объектная библиотека) — это набор откомпилированных подпрограмм, собранных в единый файл определённой структуры. Подключение библиотеки происходит на этапе компоновки исполняемого файла из объектных файлов (т.е. из тех файлов, которые получаются в результате компиляции исходного текста программы).
Необходимые объектные библиотеки входят в комплект поставки компилятора. В комплект поставки библиотек (любых) входит набор заголовочных файлов, которые содержат объявления, необходимые компилятору.
Если исходный код программы разделён на несколько файлов, то процесс компиляции и сборки происходит аналогично. Сначала все единицы компиляции по отдельности компилируются, а затем компоновщик собирает полученные объектные модули (с подключением библиотек) в исполняемый файл. Собственно, этот процесс и называется раздельной компиляцией.
Ход работы:
1. Ознакомиться с теоретическими сведениями.
2. Законспектировать тезисы.
3. Провести анализ этапов обработки программы от исходного кода к исполняемому в операционных системах на примере языка С++.
Содержание отчета
Отчет по практической работе должен содержать следующие пункты:
— название практической работы;
— краткие теоретические сведения;
— индивидуальное задание для выполнения практической работы;
— краткое описание хода выполнения работы;
— результаты выполнения работы;
Практическая работа №18
Источник: cyberpedia.su