- •Структура программы на языке Си. Этапы выполнения программы
- •1.1. Алфавит языка Си
- •1.2. Лексемы
- •1.3. Идентификаторы и ключевые слова
- •1.4. Знаки операций
- •1.5. Литералы (константы)
- •1.6. Комментарии
- •1.7. Общая структура программы на языке Си.
- •1.8. Функциональная и модульная декомпозиции
- •1.9. Этапы обработки программы.
- •1.10. Роль препроцессора.
- •1.11. Ошибки
- •2. Переменные и константы. Типы данных
- •2.1. Основные типы данных
- •2.2. Декларация (объявление) объектов
- •2.3. Константы в программах
- •2.4. Целочисленные константы
- •2.5. Константы вещественного типа
- •2.6. Символьные константы
- •2.7. Строковые константы
- •3. Обзор операций
- •3.1. Операции, выражения
- •3.2. Арифметические операции
- •3.3. Операции сравнения
- •3.4. Логические операции
- •4. Операции (продолжение).
- •4.1. Операция присваивания
- •Примеры недопустимых выражений:
- •4.2. Сокращенная запись операции присваивания
- •4.3. Преобразование типов операндов бинарных операций
- •4.4. Преобразование типов при присваивании.
- •4.5. Операция явного приведения типа
- •4.6. Операция «,» (запятая)
- •5. Стандартная библиотека языка Си
- •5.1. Стандартные математические функции
- •5.2. Потоковый ввод-вывод
- •5.3. Консольные функции вывода данных на экран
- •5.4. Консольные функции ввода информации
- •5.5. Ввод-вывод в оконных приложениях.
- •Советы по программированию
- •6. Операторы языка с.
- •7. Составление разветвляющихся алгоритмов
- •7.1. Условные операторы
- •If (выражение) оператор;
- •If (выражение) оператор 1 ;
- •If (выражение 1) оператор 1;
- •If (выражение 2) оператор 2;
- •If (выражение 3) оператор 3;
- •7.2. Оператор выбора альтернатив (переключатель)
- •7.3. Условная операция «? :»
- •8. Составление циклических алгоритмов
- •8.1. Оператор с предусловием while
- •8.2. Оператор цикла с постусловием do – while
- •8.3. Оператор цикла с предусловием и коррекцией for
- •8.4. Вложенные циклы.
- •9. Операторы передачи управления.
- •9.1. Оператор безусловного перехода goto
- •9.2. Операторы continue, break и return
- •10. Массивы
- •10.1. Одномерные массивы
- •10.2. Примеры алгоритмов, использующих одномерные массивы.
- •10.3. Многомерные массивы
- •10.4. Примеры алгоритмов, использующих двумерные массивы.
- •10.5. Компонента StringGrid
- •11. Размещение данных и программ в памяти пэвм
- •11.1. Общие понятия.
- •11.2. Кодирование целых чисел.
- •11.3. Кодирование вещественных чисел.
- •11.4. Кодирование символов.
- •Примеры кодов символов:
- •Стандартная часть таблицы символов (ascii)
- •Дополнительная часть таблицы символов
- •11.5. Операция sizeof
- •11.6. Побитовые логические операции. Операции над битами
- •11.7. Кодирование программы.
- •11.8. Регистры
- •12.1. Строки как нуль-терминированные массивы char.
- •12.2. Русификация консольных приложений.
- •12.3. Строки как переменные типа AnsiString.
- •12.4. Преобразования строковых типов.
- •12.5. Тип String в консольных приложениях.
- •13. Функции пользователя и классы памяти.
- •13.1. Сущность и предназначение функций.
- •13.2. Определение и вызов функции.
- •13.3. Прототип функции.
- •13.4. Область видимости.
- •13.5. Классы памяти объектов в языке Cи.
- •13.6. Разбиение программы на модули.
- •14. Структуры и объединения
- •14.1. Понятие структуры
- •14.2. Декларация структурного типа данных
- •14.3. Объявление структурных переменных
- •14.4. Обращение к полям структуры
- •14.5. Операции со структурой как единым целым
- •14.6. Вложенные структуры
- •14.7. Массивы структур
- •14.8. Размещение структурных переменных в памяти
- •14.9. Битовые поля
- •14.10. Объединения
- •15. Генерация псевдослучайных чисел.
- •16. Файлы в языке с
- •16.1. Типы файлов.
- •16.2. Открытие файла
- •16.3. Закрытие файла
- •16.4. Запись - чтение информации
- •А) Посимвольный ввод-вывод
- •Б) Построчный и форматированный ввод-вывод
- •В) Блоковый ввод-вывод
- •Int fflush(file *stream);
- •16.5. Текстовые файлы
- •16.6. Перенаправление стандартного ввода-вывода
- •16.7. Бинарные файлы
- •16.8. Дополнительные полезные функции
- •16.9. Простейший пример создания собственной базы данных
- •17. Указатели
- •17.1. Определение указателей
- •17.2. Связь указателей и массивов.
- •17.3. Операции над указателями (косвенная адресация)
- •17.4. Операции над указателями (косвенная адресация)
- •17.5. Массивы указателей.
- •17.6. Указатели на указатели.
- •17.7 . Указатели как параметры функций.
- •Void f1(int, const double *);
- •17.8 . Указатели на структуры
- •17.9. Ссылка
- •17.10. Указатели на функции
- •Id_функции(список аргументов);
- •18. Работа с динамической памятью
- •18.1. Динамическое выделение и освобождение памяти.
- •18.2. Создание одномерного динамического массива.
- •18.3. Создание двуxмерного динамического массива.
- •19. Операция typedef
- •20. Отладка и пошаговое выполнение программы
13.3. Прототип функции.
Функции могут располагаться в исходном файле в любом порядке. А сама исходная программа, как отмечалось вначале, может размещаться в нескольких файлах.
При этом, однако, может возникнуть ошибка компиляции, если компилятор встретит вызов функции раньше, чем ее объявление. Для устранения этого используют описания (прототипы) функций.
Описание функции заключается в приведении в начале программного файла ее прототипа (заголовка). Прототип функции сообщает компилятору о том, что далее в тексте программы будет приведено ее полное определение: в текущем или другом файле исходного текста, либо в библиотеке, содержащей ее скомпилированный (объектный) код.
Прототип функции имеет вид:
тип_результата имя_функции (список) ;
В списке перечисляются типы параметров данной функции, причем имена этих параметров в круглых скобках прототипа указывать не обязательно. Прототип завершается точкой с запятой, в то время как в определении функции за списком параметров идет не точка с запятой, а фигурные скобки с телом функции. Это позволяет компилятору различать их. Описание дает возможность компилятору проверить соответствие типов и количества параметров при фактическом вызове этой функции. В определении и в описании одной и той же функции типы и порядок следования параметров должны совпадать. Тип возвращаемого значения и типы параметров совместно определяют тип функции.
Пример описания функции fun, которая имеет три параметра типа int, один параметр типа double и возвращает результат типа double:
double fun(int, int, int, double);
Пример описания для вышеприведенной функции Min:
int Min (int x, int y);
либо
int Min (int, int);
13.4. Область видимости.
Область видимости (действия) объекта (переменной и др.) – это та часть кода (текста) программы, в которой его можно использовать.
В сложных программах ограничение этой области помогает избежать путаницы, вызванной использованием одинаковых имен в разных местах для разных целей. Например, количество чего-либо удобно обозначать буквой n. При этом в одной функции n может означать количество символов, а в другой - количество штук товара на складе. Присвоение n значения в одной функции тогда может испортить работу второй функции; но если в каждой функции своя, независимая переменная с именем n, такой проблемы не возникнет.
Основное правило видимости в языке Си: объект, объявленный внутри блока (участка программы, заключенного в фигурные скобки), как правило, виден, начиная с места его объявления и заканчивая концом этого блока ( } ). Если объявление данных лежит внутри нескольких входящих друг в друга блоков, оно считается расположенным в самом внутреннем из них. Если же нужно сделать объект видимым за пределами блока, нужно объявить его вне блока. Можно, например, объявить переменные вне всех функций; такие переменные называются глобальными, в отличие от переменных, объявленных внутри функции, называемых локальными и видимых только в пределах своей функции.
Область действия локальных данных – от точки декларации (объявления) до конца функции (блока), в которой произведено их объявление, включая все вложенные в него блоки.
Областью действия глобальных данных считается файл, в котором они определены, от точки описания до его окончания.
Если некоторое место программы входит в область видимости двух и более переменных с одинаковыми именами, объявленных на разном уровне вложенности блоков, действует та из них, которая объявлена на самом глубоком уровне. Объявление в одном и том же блоке на одном и том же уровне (или глобально - в одном и том же файле) переменных с одинаковыми именами вызывает ошибку компиляции.
Сказанное иллюстрирует пример:
void fun(void);
void fun2(int a);
int a=10;
void main(){
cout<<a<<endl; // a=10
int a=20;
cout<<a<<endl; // a=20
do{
int a=30;
cout<<a<<endl; // a=30
} while(0);
cout<<a<<endl; // a=20
for (int i=0; i<1; i++) {
int a=40;
cout<<i<<endl; // i=0
cout<<a<<endl; // a=40
}
cout<<a<<endl; // a=20
fun();
fun2(a);
}
void fun(void){
cout<<a<<endl; // a=10
}
void fun2(int a){
cout<<a<<endl; // a=20
}
Некоторые уточнения:
-
Параметры функции являются локальными переменными, их область действия - вся функция;
-
Если переменная объявлена внутри круглых скобок какого-либо оператора (например, for (int i=0; i<n: i++) { … } ), то областью ее действия одни компиляторы считают этот оператор (вместе с его телом), а другие - весь блок, в котором он находится. Рекомендуется поэтому использовать подобное место объявления, только если это не может привести к двусмысленности.
-
Область действия метки - вся функция (даже если метка лежит во вложенном блоке).
-
Функции не могут быть объявлены внутри других функций; поэтому они, как правило, являются глобальными. (При необходимости их область видимости можно ограничить с помощью не рассматриваемого здесь оператора namespace).
Замечание. Некоторые компиляторы не допускают переход с помощью goto внутрь области видимости переменной извне ("перескакивая" ее объявление), даже если сама эта переменная при этом не используется, т.к. это мешает им распределять память:
goto M;
int i;
M: // Может вызвать ошибку компиляции
Связь между функциями осуществляется через аргументы и возвращаемые функциями значения. Ее можно осуществить также через внешние, глобальные переменные.
Глобальные переменные доступны всем функциям, где они не описаны как локальные переменные. Использовать их для передачи данных между функциями довольно просто: значение, присвоенное глобальной переменной в одной функции, доступно в другой функции. Тем не менее, без нужды этого делать не рекомендуется. Необходимо стремиться к тому, чтобы функции в программе были максимально независимыми, и чтобы их интерфейс полностью определялся прототипами этих функции.