- •Основы программирования на языке Си.
- •Достоинства языка Си.
- •Будущее языка Си.
- •Использование языка Си.
- •Использование текстового редактора для подготовки программ.
- •Исходные и выполняемые файлы
- •Пример простой программы на языке Си
- •Структура простой программы
- •2. Лекция: Данные, символьные строки, директива #define.
- •Основные типы данных
- •Описание различных типов, переменные и константы
- •Символьные строки
- •Препроцессор языка Си
- •3. Лекция: Операции.
- •Основные операции
- •Дополнительные операции
- •Перечень операций языка Си
- •Операции, уровень приоритета которых равен 1
- •Операции, уровень приоритета которых равен 2
- •Операции, уровень приоритета которых равен 3
- •Операции, уровень приоритета которых равен 4
- •Операции, уровень приоритета которых равен 5
- •Операции, уровень приоритета которых равно 6
- •Операции, уровень приоритета которых равен 7
- •Операция, уровень приоритета которой равен 8
- •Операция, уровень приоритета которой равен 9
- •Операция, уровень приоритета которой равен 10
- •Операция, уровень приоритета которой равен 11
- •Операция, уровень приоритета которой равен 12
- •Операция, уровень приоритета которой равен 13
- •Операция, уровень приоритета которой равен 14
- •Операция, уровень приоритета которой равен 15
- •Примеры простых задач
- •4. Лекция: Операторы.
- •Выражения
- •Простейшие выражения
- •Операторы
- •Составные операторы
- •Оператор цикла while
- •10 Км. В последующие дни он проезжал со скоростью,
- •Изучение и использование функций printf( ) и scanf( )
- •Применение функции scanf( )
- •Подведем итог.
- •5. Лекция: преобразование типов.
- •Эквивалентность типов
- •Преобразование типов
- •Разбор программы
- •Операция приведения
- •Неявное преобразование типа
- •Арифметические преобразования
- •Явные преобразования типов
- •Синтаксис типов
- •6. Лекция: функции и переключение ввода-вывода
- •Ввод и вывод одного символа
- •Чтение одной строки
- •Чтение файла
- •Переключение и работа с файлами
- •7. Лекция: Выбор вариантов.
- •Выбор вариантов
- •Оператор if
- •Расширение оператора if
- •Операции отношения
- •Логические операции
- •Операция условия: ?:
- •Множественный выбор
- •8. Лекция: Циклы и другие управляющие средства. Структурное программирование.
- •Структурное программирование
- •Цикл с предусловием
- •Цикл со счетчиком
- •Цикл с постусловием
- •Другие управляющие операторы
- •9. Лекция: Функции.
- •Создание и использование функций
- •Аргументы функции
- •Возвращение значений
- •Локальные переменные
- •Нахождение адресов
- •Указатели, первое знакомство
- •Функции с переменным количеством аргументов
- •10. Лекция: Классы памяти и разработка программ.
- •Классы памяти и область действия
- •Автоматические переменные
- •Внешние переменные
- •Статические переменные
- •Внешние статические переменные
- •Регистровые переменные
- •11. Лекция: Препроцессор языка Си.
- •Общие сведения
- •Символические константы: #define
- •Использование аргументов с #define
- •Макроопределение или функция?
- •Включение файла: #include
- •Условная компиляция
- •12. Лекция: Массивы и указатели.
- •Указатели и массивы
- •Массивы
- •Указатели
- •Динамические объекты
- •Создание динамических объектов
- •Доступ к динамическим объектам
- •Связь между указателями и массивами
- •Инициализация массивов и классы памяти
- •Функции, массивы и указатели
- •Операции с указателями
- •13. Лекция: Символьные строки и функции над ними.
- •Строковые константы
- •Массивы символьных строк и их инициализация
- •Массив и указатель: различия
- •Указатели и строки
- •Ввод-вывод строк
- •Обработка строк
- •14. Лекция: Структуры.
- •Определение структурных переменных
- •Доступ к компонентам структуры
- •Поля битов в структурах
- •Объединения
- •Перечисления
- •Переменные структуры
- •Указатели и структуры
- •Массив структур
- •Переименование типов
- •15. Лекция: Библиотека языка Си и файлы ввода-вывода.
- •Стандартные библиотечные функции
- •Связь с файлами
- •Текстовые файлы с буферизацией
- •Распределение памяти
- •16. Лекция: Функции в примерах.
- •Функция получения случайных чисел
- •Поиск узлов из простых чисел
- •Матрица инцидентности
- •Структуры данных
- •Все операции со стеком
Использование аргументов с #define
Во избежание ошибок при вычислении выражений параметры макроопределения необходимо заключать в скобки.
#define идентификатор1 (идентификатор2, . . .) строка
Пример:
#define abs(A) (((A) > 0)?(A) : -(A))
Каждое вхождение выражения abs(arg) в тексте программы заменяется на
((arg) > 0) ? (arg) : -(arg),
причем параметр макроопределения А заменяется на arg.
Пример:
#define nmem (P,N)\
(P) -> p_mem[N].u_long
Символ \ продолжает макроопределение на вторую строчку. Это макроопределение уменьшает сложность выражения, описывающего массив объединений внутри структуры.
Макроопределение с аргументами очень похоже на функцию, поскольку аргументы его заключены в скобки:
/* макроопределение с аргументами */
#define SQUARE(x) x*x
#define PR(x) printf("x равно %d.\n", x)
main( )
{
int x = 4; int z;
z = SQUARE(x);
PR(z);
z = SQUARE(2);
PR(z);
PR(SQUARE(x));
PR(SQUARE(x+2));
PR(100/SQUARE(2));
PR(SQUARE(++x));
}
Всюду, где в нашей программе появляется макроопределение SQUARE(x), оно заменяется на x*x . В отличие от наших прежних примеров, при использовании этого макроопределения мы можем совершенно свободно применять символы, отличные от x. В макроопределении 'x' замещается символом, использованным в макровызове программы. Поэтому макроопределение SQUARE(2) замещается на 2*2. Таким образом, x действует как аргумент. Однако, аргумент макроопределения не работает - точно так же, как аргумент функции. Вот результаты выполнения программы:
z равно 16.
z равно 4.
SQUARE(x) равно 16.
SQUARE(x+2) равно 14.
100/SQUARE(2) равно 100.
SQUARE(++x) равно 30.
Первые две строки очевидны. Заметим, что даже внутри двойных кавычек в определении PR переменная замещается соответствующим аргументом. Все аргументы в этом определении замещаются. Рассмотрим третью строку:
PR(SQUARE(x));
Она становится следующей строкой:
printf("SQUARE(x) равно %d.\n", SQUARE(x));
после первого этапа макрорасширения. Второе SQUARE(x) расширяется, превращаясь в x*x, а первое остается без изменения, потому что теперь оно находится внутри кавычек в операторе программы, и таким образом защищено от дальнейшего расширения. Окончательно строка программы содержит
printf("SQUARE(x) равно %d.\n",x*x);
и выводит на печать
SQUARE(x) равно x*x.
Если макроопределение включает аргумент с двойными кавычками, то аргумент будет замещаться строкой из макровызова. Но после этого он в дальнейшем не расширяется, даже если строка является еще одним макроопределением. В нашем примере переменная x стала макроопределением SQUARE(x) и осталась им. Вспомним, что x=4. Это позволяет предположить, что SQUARE(x+2) будет равно 6*6 или 36. Но напечатанный результат говорит, что получается число 14. Причина такого результата такова: препроцессор не делает вычислений. Он только замещает строку. Всюду, где наше определение указывает на x, препроцессор подставит строку x+2.
Таким образом,
x*x становится x+2*x+2
Если x равно 4, то получается
4+2*4+2=4+8+2=14
Вызов функции передает значение аргумента в функцию во время выполнения программы. Макровызов передает строку аргументов в программу до ее компиляции.