Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
билеты информатика.rtf
Скачиваний:
39
Добавлен:
02.05.2015
Размер:
6.9 Mб
Скачать

Препроцессор Си

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

  • Замена триграфов ??=??(??) (и других) символами #[]

  • Замена комментариев пустыми строками

  • Включение файла — #include

  • Макроподстановки — #define

  • Условная компиляция — #if, #ifdef, #elif, #else, #endif

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

Директивы

Директивой препроцессора (или командной строкой препроцессора[1]) называется строка в исходном коде, которая начинается с символа # и следующего за ним ключевого слова препроцессора. Есть чётко определённый список ключевых слов:

  • define — задаёт макроопределение (макрос) или символическую константу

  • undef — отменяет предыдущее определение

  • include — вставляет текст из указанного файла

  • if — осуществляет условную компиляцию при истинности константного выражения

  • ifdef — осуществляет условную компиляцию при определённости символической константы

  • ifndef — осуществляет условную компиляцию при неопределённости символической константы

  • else — ветка условной компиляции при ложности выражения

  • endif — конец ветки условной компиляции

  • line — препроцессор изменяет номер текущей строки и имя компилируемого файла

  • error — выдача диагностического сообщения

  • pragma — действие, зависящее от конкретной реализации компилятора

  • пустое слово - пустое действие.

Функции Включение

Препроцессор Си, встречая следующие директивы:

#include "..."

или

#include <...>

полностью копирует содержимое указанного файла в файл, в котором указана эта директива, в месте вызова директивы. Эти файлы обычно (хотя скорее, всегда) содержат определение интерфейса для различных функций библиотек и типов данных, которые должны быть подключены перед их использованием; таким образом, директива #include обычно указывается в начале (заголовке) файла. По этой причине подключаемые файлы и называются заголовочными. Некоторые содержат примеры из стандартной библиотеки Си (<math.h> и <stdio.h>), обеспечивая математические функции и функции ввода-вывода соответственно.

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

Условная компиляция

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

В общем случае, программисту необходимо использовать конструкцию наподобие этой:

#ifndef FOO_H

#define FOO_H

...(код заголовочного файла)...

#endif

Такая «защита макросов» предотвращает двойное подключение заголовочного файла путем проверки существования этого макроса, который имеет то же самое имя, что и заголовочный файл. Определение макроса FOO_H происходит, когда заголовочный файл впервые обрабатывается препроцессором. Затем, если этот заголовочный файл вновь подключается, FOO_H уже определен, в результате чего препроцессор пропускает полностью текст этого заголовочного файла.

То же самое можно сделать, включив в заголовочный файл директиву:

#pragma once

Условия препроцессора можно задавать несколькими способами, например:

#ifdef x

...

#else

...

#endif

или

#if x

...

#else

...

#endif

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

19.функции в языке. Объявление функции, функция мэйн20 и 21 здесь же

Функция - это самостоятельная единица программы, созданная для решения конкретной задачи. Функция в языке С играет ту же роль, что и подпрограммы или процедуры в других языках. Функциями удобно пользоваться, например, если необходимо обработать один и тот же код программы. Как и переменные, функции надо объявлять (declare). Функцию необходимо объявить до её использования. Запомните это простое правило - сначала объяви, а потом используй. Каждая функция языка С имеет имя и список аргументов (формальных параметров).Функции могут возвращать значение. Это значение может быть использовано далее в программе. Так как  функция может вернуть какое-нибудь значение, то обязательно нужно указать тип данных возвращаемого значения. Если тип не указан, то по умолчанию предполагается, что функция возвращает целое значение (типа int). После имени функции принято ставить круглые скобки (это касается вызова функции её объявления и описания). В этих скобках перечисляются параметры функции, если они есть. Если у функции нет параметров, то при объявлении и при описании функции вместо <список параметров> надо поставить void - пусто.Основная форма описания (definition) функции имеет вид:тип <имя функции>(список параметров){        тело функции}

Объявление (прототип) функции имеет вид:

тип <имя функции>(список параметров);

Обратите внимание на то, что при описании функции после заголовка функциитип <имя функции>(список параметров) точка с запятой не ставиться, а при объявлении функции точка с запятой ставиться.

Вызов функции делается следующим образом:

<имя функции>(параметры);

или

<переменная>=<имя функции>(параметры);

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

Приведем пример вызова функции, которая будет печатать строку "Вызвали функцию" на экран./* Используем свою функцию */#include <stdio.h>void main(void)                    // Точка входа в программу{      void function1(void);      // Объявление функции      function1();              //  Вызов функции}/* Описание функции  */void function1(void)           // Заголовок функции{                                      // Начало тела функции            printf("Вызвали функцию\n");}                                      //  Конец тела функцииРезультатом работы программы будет строка напечатанная на экране. Обратите внимание на заголовок в описании функции! После него не ставится точка с запятой.В теле функции main() мы объявили функцию function1(), затем её вызвали. В теле нашей функции function1() мы вызываем функцию printf(). А где же объявлена функция printf() ? Если вы внимательно посмотрите текст программы, то увидите строку #include <stdio.h>, как говорилось ранее эта строка говорит компилятору, чтобы тот включил в текст программы файл с объявлениями функций стандартного ввода/вывода (standart input/output). Аха! Значит функция printf() объявлена именно там! Директива препроцессора (preprocessor directive) просто вставляет текстовый файл stdio.h в текст нашей программы. Причем вставляет туда где стоит эта директива. Если вы уберете или закоментируете строку #include <stdio.h>, то программа работать не будет потому что функция printf() не будет объявлена. Компилятор просто выдаст ошибку - function 'printf' should have a prototype (Функция 'printf' должна иметь прототип).Обратите внимание ещё на то, что тип возвращаемого значения у нашей функции void (пусто). Это значит, что функция не будет возвращать никакого значения.