Скачать презентацию Введение в язык С Лекции Толмачева Марина Скачать презентацию Введение в язык С Лекции Толмачева Марина

Презентация10_C.ppt

  • Количество слайдов: 162

Введение в язык С Лекции – Толмачева Марина Владимировна Практика – Юхта Павел Валерьевич Введение в язык С Лекции – Толмачева Марина Владимировна Практика – Юхта Павел Валерьевич

План курса o o o o o o o 1 2 3 4 5 План курса o o o o o o o 1 2 3 4 5 6 7 8 8. 1 8. 2 8. 3 8. 4 8. 5 8. 6 8. 7 8. 8 8. 9 8. 10 8. 11 8. 12 8. 15 8. 17 8. 14 8. 16 Место вычислительных систем в составе навигационной системы Принципы построения ЭВМ Функционирование ЭВМ на программном уровне Классификация микропроцессоров Иерархическая организация памяти ЭВМ Управление периферийными устройствами ЭВМ Классификация ПО Основы языка С Пример простой программы на языке С Создание исполняемой программы Алфавит, идентификаторы, служебные слова Структура функции на языке С Структура программы на языке С Данные: переменные и константы Данные: типы данных Операции Символьные строки. Форматированный ввод и вывод Отношения, логические операции и логические выражения Условные операторы Операторы цикла Указатели. Указательные выражения. Указатели и массивы Функции Файловый ввод / вывод Структуры Битовые поля

Рекомендуемая литература o В. В. Подбельский, С. С. Фомин Прграммирование на языке Си o Рекомендуемая литература o В. В. Подбельский, С. С. Фомин Прграммирование на языке Си o M. Уэйт, С. Прата, Д. Мартин Язык Си o Шилд Г. Полный справочник по С. 4 изд

Место вычислительных систем в составе навигационной системы Место вычислительных систем в составе навигационной системы

Принципы построения ЭВМ o o o цифровое представление данных; программное управление; микропрограммное управление; адресуемость Принципы построения ЭВМ o o o цифровое представление данных; программное управление; микропрограммное управление; адресуемость памяти; магистральная связь.

Функционирование ЭВМ на программном уровне Признаки результатов Управл. сигналы УУ АЛУ Операнды Адрес а Функционирование ЭВМ на программном уровне Признаки результатов Управл. сигналы УУ АЛУ Операнды Адрес а Результаты Команды Программы, данные ОЗУ ВЗУ Программы, данные УВВ Программы, данные Структурная схема ЭВМ. Результаты

Функционирование ЭВМ на программном уровне (слайд 2) Перечень команд, которые может исполнять процессор ЭВМ, Функционирование ЭВМ на программном уровне (слайд 2) Перечень команд, которые может исполнять процессор ЭВМ, называется системой машинных команд ЭВМ. Одна машинная команда (команда ЭВМ), как правило, занимает одну ячейку ОЗУ и задает строго определенную последовательность действий ЭВМ по преобразованию данных или управлению ее компонентами. В общем случае машинная команда состоит из двух частей – операционной и адресной. Первая часть содержит обычно два поля (части) - поле кода операции (КОП) и поле признаков (П). Вторая часть команды может содержать до четырех полей – поле признаков адресации (ПА) и поля адресов (А 1, А 2, А 3). ПА КОП П А 1 А 2 Формат машинной команды А 3

Функционирование ЭВМ на программном уровне (слайд 3) В общем случае исполнение команды ЭВМ (рабочий Функционирование ЭВМ на программном уровне (слайд 3) В общем случае исполнение команды ЭВМ (рабочий цикл процессора) складывается из трех фаз: 1. выборка команды, когда с использованием адреса сформированного в процессоре, из ОЗУ извлекается код команды, 2. выборка операндов, когда с использованием адресов, сформированных в процессоре, из ОЗУ извлекаются операнды (данные, участвующие в операции), 3. выполнение операции, когда процессор выполняет операцию, код которой содержится в команде, над извлеченными из памяти операндами.

Пример составления программы в машинных кодах Составим программу вычисления одного значения функции: при A Пример составления программы в машинных кодах Составим программу вычисления одного значения функции: при A = 3; x = 4; B = 5 для гипотетической одноадресной ЭВМ Пусть ЭВМ имеет следующую систему команд. Дес. № Операция Дв. п. п. ССЧ 1 Пересылка содержимого ячейки ОЗУ в АЛУ 1 0001 2 Пересылка результата операции из АЛУ в ОЗУ 2 0010 3 Сложение 3 0011 4 Умножение 4 0100 5 Стоп 5 0101

Пример составления программы в машинных кодах (слайд 2) Адрес ячейки ОЗУ Команда КОП Адрес Пример составления программы в машинных кодах (слайд 2) Адрес ячейки ОЗУ Команда КОП Адрес 0 1 5 1 4 6 2 3 7 3 2 8 4 5 Комментарий Пересылка числа А из ячейки 5 в АЛУ Умножение числа А на x из ячейки 6 Сложение результата с числом В из яч. 7 Пересылка результата в яч. 8 ОЗУ Стоп 5 3 А 6 4 x 7 5 В 8 17 y

Пример составления программы в машинных кодах (слайд 3) Адрес ячейки ОЗУ Команда КОП Адрес Пример составления программы в машинных кодах (слайд 3) Адрес ячейки ОЗУ Команда КОП Адрес 0000 0001 0101 0001 0100 0110 0011 0111 0010 1000 0101 Комментарий Пересылка числа А из ячейки 5 в АЛУ Умножение числа А на x из ячейки 6 Сложение результата с числом В из яч. 7 Пересылка результата в яч. 8 ОЗУ Стоп 0101 00000011 А 0110 00000100 x 0111 00000101 В 1000 0001 y

Классификация микропроцессоров Процессор является устройством, исполняющим программу - последовательность команд (инструкций), задуманную программистом и Классификация микропроцессоров Процессор является устройством, исполняющим программу - последовательность команд (инструкций), задуманную программистом и оформленную в виде модуля программного кода. IBM PC-совместимый компьютер Реализуется концепция хранимой программы: программы и данные хранятся в одной и той же памяти. Выполняемые действия определяются блоком УУ и АЛУ, которые вместе являются основой центрального процессора. Центральный процессор выбирает и исполняет команды из памяти последовательно, адрес очередной команды задается "счетчиком адреса" в блоке управления. Этот принцип исполнения называется последовательной передачей управления.

Классификация микропроцессоров (слайд 2) Существует множество архитектур процессоров, которые делятся на две глобальные категории Классификация микропроцессоров (слайд 2) Существует множество архитектур процессоров, которые делятся на две глобальные категории - RISC и CISC. RISC - Reduced (Restricted) Instruction Set Computer - процессоры (компьютеры) с сокращенной системой команд. Эти процессоры обычно имеют набор однородных регистров универсального назначения, причем их число может быть большим. Система команд отличается относительной простотой, коды инструкций имеют четкую структуру, как правило, с фиксированной длиной. В результате аппаратная реализация такой архитектуры позволяет с небольшими затратами декодировать и выполнять эти инструкции за минимальное (в пределе 1) число тактов синхронизации. Определенные преимущества дает и унификация регистров.

Классификация микропроцессоров (слайд 3) CISC - Complete Instruction Set Computer - процессоры (компьютеры) с Классификация микропроцессоров (слайд 3) CISC - Complete Instruction Set Computer - процессоры (компьютеры) с полным набором инструкций, к которым относится и семейство х86. Состав и назначение их регистров существенно неоднородны, широкий набор команд усложняет декодирование инструкций, на что расходуются аппаратные ресурсы. Возрастает число тактов, необходимое для выполнения инструкций.

Иерархическая организация памяти ЭВМ СОЗУ КЭШ ОП ВЗУ Иерархическая организация памяти ЭВМ СОЗУ КЭШ ОП ВЗУ

Управление периферийными устройствами ЭВМ Ядро любой ЭВМ образуют процессор и ОЗУ. Однако, кроме них, Управление периферийными устройствами ЭВМ Ядро любой ЭВМ образуют процессор и ОЗУ. Однако, кроме них, в состав ЭВМ входят различные периферийные устройства (ПУ), а именно, ВЗУ и устройства ввода-вывода (УВВ) (клавиатура, дисплей, принтер и т. п. ). Управление этими устройствами осуществляется в целях обмена информацией между ними и ядром ЭВМ. Передача информации из ПУ в ЭВМ называется операцией ввода, а из ЭВМ в ПУ – операцией вывода.

Классификация ПО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Системное Средства контроля и диагностики Системы программирования Прикладное Операционная система Классификация ПО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Системное Средства контроля и диагностики Системы программирования Прикладное Операционная система Пакеты прикладных программ Прикладные программы пользователей

Операционная система и ее место в общей структуре компьютера Прикладное ПО компиляторы Редакторы Интерпретаторы Операционная система и ее место в общей структуре компьютера Прикладное ПО компиляторы Редакторы Интерпретаторы команд Операционная система Машинный язык Микроархитектура Физические устройства

Основы языка С Пример простой программы на языке С /* Программа вычисляет значение у=A*x+B Основы языка С Пример простой программы на языке С /* Программа вычисляет значение у=A*x+B при A=3, x=4, B=5 и выводит значение у на экран*/ #include //подключение библиотеки для вывода на экран main() { int A=3, x=4, B=5, y; //определение переменных y=A*x+B; //вычисление printf("y=%d", y); //вывод на экран у=17 return 0; }

Схема подготовки исполняемой программы компилятор Исходный текст на языке СИ Препроцессор Полный текст программы Схема подготовки исполняемой программы компилятор Исходный текст на языке СИ Препроцессор Полный текст программы Включаемые файлы Объектный код программы1 Компоновщик Исполняемая программа ………. Объектный код программы. N Схема подготовки исполняемой программы Анализ и синтез

Компиляция Компилятор (англ. compiler — составитель, собиратель) читает всю программу целиком, делает ее перевод Компиляция Компилятор (англ. compiler — составитель, собиратель) читает всю программу целиком, делает ее перевод и создает вариант программы на машинном языке. Вначале препроцессор сканирует текст программы в поисках строк начинающихся с символа #. Такие строки воспринимаются препроцессором как команды (директивы), которые определяют действия по преобразованию текста. Директива #include определяет, какие текстовые файлы нужно включить в этом месте программы. Если в нашем примере мы бы забыли написать строку #include , то на этапе препроцессорной обработки выдастся ошибка: «Function ‘printf’ should have a prototype» - не описана функция printf. Если ошиблись в написании файла, то: «Unable to open include file ‘stdi. h’ – невозможно открыть файл.

Функции компилятора o Является распознавателем для языка исходной программы. Получает на вход цепочку символов Функции компилятора o Является распознавателем для языка исходной программы. Получает на вход цепочку символов входного языка, проверяет ее принадлежность языку и выявляет правила, по которым эта цепочка построена. o Генерирует результирующую программу. На выходе создается цепочка выходного языка по определенным правилам. Распознавателем сгенерированной цепочки объектной программы будет выступать вычислительная система.

Основные фазы компиляции o Лексический анализ выполняет сканер, который читает литеры программы (символы) на Основные фазы компиляции o Лексический анализ выполняет сканер, который читает литеры программы (символы) на исходном языке и строит из них слова (лексемы) исходного языка. На входе сканера (лексического анализатора) текст исходной программы, выходная информация передается для дальнейшей обработки на этап синтаксического разбора. o Синтаксический разбор − это основная часть компилятора на этапе анализа. Здесь в тексте исходной программы выделяются синтаксические конструкции. Кроме того, проверяется синтаксическая правильность программы. Если мы допустим синтаксическую ошибку в коде программы, например, забудем поставить ; в конце строки, то компилятор выдаст нам ошибку, например такую: Statement missing ; - неверное утверждение ;

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

Основные фазы компиляции (продолжение 2) o Генерация кода − это фаза, на которой непосредственно Основные фазы компиляции (продолжение 2) o Генерация кода − это фаза, на которой непосредственно порождаются команды, составляющие предложения выходного языка и текст результирующей программы в целом. Кроме этого, генерация обычно включает в себя и оптимизацию. o Таблицы идентификаторов – это специальным образом организованные наборы данных, которые хранят информацию об элементах исходной программы. В результате работы компилятора создается объектный код программы, который заносится в файл с расширением *. obj или *. o.

Компоновка или редактирование связей Редактор связи физически связывает файлы, внесенные в список компоновки, в Компоновка или редактирование связей Редактор связи физически связывает файлы, внесенные в список компоновки, в один программный файл и разрешает внешние ссылки. Внешняя ссылка создается каждый раз, когда программа из одного файла ссылается на код из другого файла. В нашем примере на этапе компоновки к нашей программе добавится ссылка на программу (функцию) printf. В создаваемом исполняемом файле будет хранится и наша программа и printf и связь между ними.

Идентификаторы Идентификатор. Последовательность букв, цифр и символов подчеркивания Идентификаторы Идентификатор. Последовательность букв, цифр и символов подчеркивания "_" , начинающаяся с буквы или символа подчеркивания, считается идентификатором языка С. Примеры идентификаторов: КОМ_16, size 88, _MIN, TIME, time Прописные и строчные буквы различаются, т. е. два последних идентификатора различны. Неправильные имена: $Z**, 1 fl, don’t, my-name

Идентификаторы (слайд 2) Идентификаторы могут иметь любую длину, но компилятор учитывает не более 31 Идентификаторы (слайд 2) Идентификаторы могут иметь любую длину, но компилятор учитывает не более 31 -го символа от начала идентификатора. В некоторых компиляторах это ограничение еще более жесткое, и учитываются только первые 8 символов любого идентификатора. В этом случае идентификаторы NUMBER_OF_ROOM и NUMBER_OF_TEST в программе будут неразличимы.

Служебные (ключевые) слова auto break case char double else enum extern int long return Служебные (ключевые) слова auto break case char double else enum extern int long return struct switch registe r typedef union const cont inue for default do goto if short Signed sizeof static unsigne d void volatil e while float Идентификаторы, начинающиеся с одного или двух символов подчеркивания зарезервированы для использования в библиотеках и компиляторах. Поэтому такие идентификаторы не рекомендуется выбирать в качестве имен в прикладной программе на языке С.

Структура функции на языке С заголовок Директива препроцессора #include <stdio. h> main() Имя функции Структура функции на языке С заголовок Директива препроцессора #include main() Имя функции с аргументами тело int A, x, B, y; A=3; x=4; B=5; y=A*x+B; printf("y=%d", y); Оператор описания Операторы присваивания Операторы вызова функции Структура функции в языке и: заголовок и тело.

Структура программы на языке Си Си-программа Функция, с которой начинается выполнение программы #Заголовок main() Структура программы на языке Си Си-программа Функция, с которой начинается выполнение программы #Заголовок main() Операторы функция N Функции – это строительные блоки языка Си Операторы Функции состоят из операторов функция M Операторы Структура программы

Данные Бит Байт Слово o Наименьшая единица памяти называется бит. Она может принимать одно Данные Бит Байт Слово o Наименьшая единица памяти называется бит. Она может принимать одно из двух значений: 0 или 1. o Байт - 8 бит. Байт удобно использовать, например, для представления целых чисел в диапазоне от 0 до 255 или для кодирования набора символов. o Слово обычно содержит 16 или 32 бита.

Целые числа Один байт 0 0 0 1 1 1 22 21 20 4+2+1=7 Целые числа Один байт 0 0 0 1 1 1 22 21 20 4+2+1=7 Двоично представление числа 7 в памяти машины. У целого числа никогда не бывает дробной части и, согласно правилам языка С, десятичная точка в его записи всегда отсутствует. В качестве примера можно привести числа: 2, -23, 2048.

Представление числа в формате с плавающей точкой + 31415926 1 знак Дробная часть Показатель Представление числа в формате с плавающей точкой + 31415926 1 знак Дробная часть Показатель степени + . 31415926 *101=3. 1415926 Десятичное представление числа p в формате с плавающей точкой

Числа с плавающей точкой соответствуют тому, что математики называют Числа с плавающей точкой соответствуют тому, что математики называют "вещественными числами". Пример: 2. 75, 3. 16 Е 7, 7. 00. 2 е-8, . 314159 Е 1, 0. 0 Запись вида "3. 16 Е 7" означает число, полученное в результате умножения 3. 16 на 10 в седьмой степени, т. е. на 1 с семью нулями. Число 7 называется "порядком" (показателем степени при основании 10). Каждая вещественная константа состоит из следующих o o o частей: целая часть (десятичная целая константа); десятичная точка; дробная часть (десятичная целая константа); признак показателя "е" или "Е"; показатель десятичной степени десятичная целая константа, возможно, со знаком).

Числа с плавающей точкой + 31415926 1 знак Мантисса Порядок + . 31415926 *101=3. Числа с плавающей точкой + 31415926 1 знак Мантисса Порядок + . 31415926 *101=3. 1415926 Десятичное представление числа p в формате с плавающей точкой

Типы данных Ключевые слова Используются для представления int Размещение в памяти машины целые типы Типы данных Ключевые слова Используются для представления int Размещение в памяти машины целые типы данных long short целых чисел unsigned char целых чисел и символов float вещественных чисел double типы данных с "плавающей точкой"

Типы int, short и long Стандартный вариант: o short -2 байта; o int – Типы int, short и long Стандартный вариант: o short -2 байта; o int – 2 или 4 байта в зависимости от компилятора; o long – 4 байта. Все данные типов int, short и long являются "числами со знаком", т. е. допустимыми значениями переменных этих типов могут быть только целые числа - положительные, отрицательные и нуль.

Описание данных целого типа При описании данных необходимо ввести только тип, за которым должен Описание данных целого типа При описании данных необходимо ввести только тип, за которым должен следовать список имен переменных. Примеры: int graf; short stops; long grad; int h, c, g;

Целые константы Если целое начинается с цифры 0, оно интерпретируется как Целые константы Если целое начинается с цифры 0, оно интерпретируется как "восьмеричное" число. Восьмеричные числа - это числа, представляемые "по основанию восемь" (т. е. их запись состоит из комбинаций степеней числа восемь). o Целое, начинающееся с символом 0 х или 0 Х интерпретируется как шестнадцатеричное число, т. е. число, записываемое по основанию 16. Десятичное Восьмеричное Шестнадцатеричное 16 020 OX 10 255 0377 Oxff

Именованные константы Инициализация тип имя_ переменной=начальное значение; Примеры: float pi=3. 1415, сс=1. 23; unsigned Именованные константы Инициализация тип имя_ переменной=начальное значение; Примеры: float pi=3. 1415, сс=1. 23; unsigned int year=2011;

Именованные константы. Квалификатор типа – const тип имя константы =значение константы; const - квалификатор Именованные константы. Квалификатор типа – const тип имя константы =значение константы; const - квалификатор типа, указывающий, что определяемый объект имеет постоянное значение, т. е. доступен только для чтения. Примеры const double Е=2. 718282; const long N=9999; const F=765;

Препроцессорная директива #define имя константы значение константы Примеры #define E 2. 718282 BSP_VERSION_MAJOR 3 Препроцессорная директива #define имя константы значение константы Примеры #define E 2. 718282 BSP_VERSION_MAJOR 3 BSP_VERSION_MINOR 19 BSP_VERSION_BETA 1

Отличия определения именованной константы от определения препроцессорной константы с таким же значением Именованная константа: Отличия определения именованной константы от определения препроцессорной константы с таким же значением Именованная константа: const double e=2. 718282; Явно определен тип Препроцессорная константа #define E 2. 718282 Тип не определен Если в тексте программы double r=E , то препроцессор сформирует такой текст: double r = 2. 718282; Далее текст от препроцессора поступает к компилятору, который уже "и не вспомнит" о существовании имени E.

Явное преобразование типов: операция приведения типов (тип)выражение унарное выражение (ранг 2) Примеры: (float)x/2; (float)4; Явное преобразование типов: операция приведения типов (тип)выражение унарное выражение (ранг 2) Примеры: (float)x/2; (float)4; #define ADR_BASE #define ADR_OFFSET/4 0 x 80000000 0 x 1 c 0000 adr=(unsigned int)(ADR_BASE+ADR_OFFSET/4);

Отношения Отношение определяется как пара арифметических выражений, соединенных (разделенных) знаком операции отношения. Знаки операций Отношения Отношение определяется как пара арифметических выражений, соединенных (разделенных) знаком операции отношения. Знаки операций отношения Знак Значение Ранг == равно 7 != неравно 7 < меньше, чем 6 <= меньше или равно 6 > больше, чем 6 >= больше или равно 6

Отношения (слайд 2) Примеры отношений: а-b > 6. 3 (х-4)*3==12 6<=44 Арифметические операции имеют Отношения (слайд 2) Примеры отношений: а-b > 6. 3 (х-4)*3==12 6<=44 Арифметические операции имеют более высокий ранг, чем операции отношений, поэтому в первом примере для выражения а-b не нужны скобки. В языке С принято, что отношение имеет значение 1, если оно истинно, и равно 0, если оно ложно. Примеры: 6<=44 значение 1 -1>0 значение 0.

Логические операции Таблицы истинности логических операций Отрицание, логическое НЕ Операнд Значение 0 1 1 Логические операции Таблицы истинности логических операций Отрицание, логическое НЕ Операнд Значение 0 1 1 0 Дизъюнкция, логическое ИЛИ Операнд 1 Операнд 2 Значение Конъюнкция, логическое И Операнд 1 Операнд 2 Значение 0 0 0 1 0 1 1 0 0 0 1 1 1

Логические операции и логические выражения Знаки логических операций Знак ! && || Значение отрицание, Логические операции и логические выражения Знаки логических операций Знак ! && || Значение отрицание, логическое НЕ конъюнкция, . логическое И дизъюнкция, логическое ИЛИ Ранг 2 11 12

Таблица истинности x y 0 0 0 1 1 x&&y x||y !x Таблица истинности x y 0 0 0 1 1 x&&y x||y !x

Таблица истинности x y x&&y x||y !x 0 0 1 0 1 1 1 Таблица истинности x y x&&y x||y !x 0 0 1 0 1 1 1 0 0 1 1 1 1 0

Логические операции и логические выражения (слайд 2) Как правило, логические операции применяются к отношениям. Логические операции и логические выражения (слайд 2) Как правило, логические операции применяются к отношениям. Например: а+b>с && а+с>b && b+с>а Задание Определите, истинны или ложны выражения: 1. a && b && c при a=1, b=1, c=0 2. a || b || c при a=1, b=1, c=0 3. !( a && b && c) при a=1, b=1, c=0 4. (0) 5. (100)

Основные формы управления процессом вычисления 1. Выполнение последовательности операторов. 2. Использование проверки истинности условия Основные формы управления процессом вычисления 1. Выполнение последовательности операторов. 2. Использование проверки истинности условия для выбора между различными возможными способами действия. 3. Выполнение определенной последовательности операторов до тех пор, пока некоторое условие истинно.

Сокращенная форма условного оператора if() if (выражение_условие) оператор; или if (выражение_условие) { оператор1; …………… Сокращенная форма условного оператора if() if (выражение_условие) оператор; или if (выражение_условие) { оператор1; …………… оператор. N; } где в качестве выражения_условия могут использоваться: арифметическое выражение, отношение и логическое выражение. Оператор, включенный в условный, выполняется только в случае истинности (т. е. при ненулевом значении) выражения_условия.

Сокращенная форма условного оператора if() (слайд 2) Пример: if (х < 0) х=-х; Схема Сокращенная форма условного оператора if() (слайд 2) Пример: if (х < 0) х=-х; Схема условного оператора условие Ложно (0) Истинно (!0) Операторы

Программа с условным оператором #include <stdio. h> int main(void) { int mark; printf( Программа с условным оператором #include int main(void) { int mark; printf("Введите количество набранных очков"); scanf("%d", &mark); if(mark > 80) printf("n. Поздравляем! Вы приняты!n"); return 0; }

Полная форма условного оператора if() if (выражение _условие) оператор 1; else оператор _2; или Полная форма условного оператора if() if (выражение _условие) оператор 1; else оператор _2; или if (выражение_условие) { оператор1; …………… оператор. N; } еlse { } оператор1; …………… оператор. N;

Полная форма условного оператора if() (слайд 2) Пример: if (х > 0) b=x ; Полная форма условного оператора if() (слайд 2) Пример: if (х > 0) b=x ; else b=-x; Схема условного оператора Истинно условие (!0) условным выражением Оператор_1 Ложно (0) else Оператор_2

Условное выражение В языке С имеется короткий способ записи одного из видов оператора if-else. Условное выражение В языке С имеется короткий способ записи одного из видов оператора if-else. Он называется "условным выражением" и использует операцию условия - ? : . Эта операция состоит из двух частей и содержит три операнда. Пример: 1. Короткий способ записи x = (y < 0 )? -y : y; 2. Способ записи с помощью if-else if(у < 0) х = -у; else х = у;

Условное выражение (слайд 2) Условное выражение в общем виде: выражение 1? Выражение 2: выражение Условное выражение (слайд 2) Условное выражение в общем виде: выражение 1? Выражение 2: выражение 3 Пример: int a=-123; (a)? printf("n. TRUEn"): printf("n. FALSEn");

Вложенные условные операторы if Оператор if является вложенным, если он вложен, т. е. находится Вложенные условные операторы if Оператор if является вложенным, если он вложен, т. е. находится внутри другого оператора if ил Во вложенном условном операторе фраза else всегда ассоциирована с ближайшим if в том же блоке. Стандарт С 89 допускает 15 уровней вложенности условных операторов, С 99 – 127 уровней.

Вложенные условные операторы if. Пример #include <stdio. h> int main(void) { int magic=77; //магическое Вложенные условные операторы if. Пример #include int main(void) { int magic=77; //магическое число int guess; //попытка игрока printf("”Угадай магическое число: "); scanf("%d", &guess); if(guess == magic) printf("n Верно!"); else if(guess > magic) printf("n — Слишком большое число!"); else printf("n — Слишком малое число!"); return 0; }

Оператор выбора switch (часто его называют переключателем) предназначен для выбора ветви вычислительного процесса исходя Оператор выбора switch (часто его называют переключателем) предназначен для выбора ветви вычислительного процесса исходя из значения управляющего выражения. switch (выражение) { case постоянная 1: последовательность операторов break; case постоянная. N: последовательность операторов break; . default последовательность операторов }

Оператор выбора switch. Пример1 #include <stdio. h> int main(void ) { unsigned int fl; Оператор выбора switch. Пример1 #include int main(void ) { unsigned int fl; printf("fl="); scanf("%d", &fl); switch (fl) { case 0 : printf("Режим Контроль (test)n"); break; case 1 : printf("Режим Работа (work)n"); break; case 2 : printf("Режим Стенд (stand)n"); break; default: printf(" Неверно введен режим (err)n"); } return 0; }

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

Оператор выбора switch. Пример2 #include <stdio. h> int main(void ) { unsigned int ch=0; Оператор выбора switch. Пример2 #include int main(void ) { unsigned int ch=0; printf("Введите, пожалуйста, букву: n"); scanf("%c", &ch); if(ch >= 'a' && ch <= 'z') //разрешены только строчные буквы { switch (ch) { case 'a': printf(“АПЕЛЬСИНn”); break; case 'b': printf(“БАНАНn”); break; case 'c': printf(“СЛИВАn"); break; default: printf(“НЕИЗВЕСТНЫЙn"); } } else printf("!!! Я распознаю только строчные буквы. n"); return 0; }

Оператор выбора switch (слайд 3) Об операторе switch важно помнить следующее: n n В Оператор выбора switch (слайд 3) Об операторе switch важно помнить следующее: n n В управляющем выражении можно использовать переменные целого или символьного типа, но только не с плавающей запятой. Оператор switch отличается от if тем, что в нем управляющее выражение проверяется только на равенство с постоянными, в то время как в if проверяется любой вид отношения или логического выражения. В одном и том же операторе switch никакие два оператора case не могут иметь равных постоянных. Если в управляющем выражении оператора встречаются символьные константы, они автоматически преобразуются к целому типу.

Операции увеличения и уменьшения ++ и --. Инкремент и декремент - унарные операции (с Операции увеличения и уменьшения ++ и --. Инкремент и декремент - унарные операции (с одним операндом) увеличения/уменьшения операнда на 1. Каждая из этих операций может быть префиксной (prefix)и постфиксной (postfix). ++ инкремент (автоувеличение) 1. ++i - увеличение значения операнда на 1 до его использования (префиксная форма). 2. i++ - увеличение значения операнда на 1 после его использования. (постфиксная форма)

Операции увеличения и уменьшения ++ и -- (слайд 2) Примеры: при n=4; y=n++*2; в Операции увеличения и уменьшения ++ и -- (слайд 2) Примеры: при n=4; y=n++*2; в результате: y =8, n=5 y=++n*2; в результате: y =10, n=5 -- декремент (автоуменьшение). 1. --i - уменьшение значения операнда на 1 до его использования (префиксная форма). 2. i-- - уменьшение значения операнда на 1 после его использования. (постфиксная форма)

Программа пересчета км в морские мили. Вариант1 #include <stdio. h> #define M_MILE 1. 853 Программа пересчета км в морские мили. Вариант1 #include #define M_MILE 1. 853 //1 морская миля -1852 m int main(void) { float ret, km=2; ret=km*(float)M_MILE; printf("n km t mile n"); printf(" %4. 2 f t %4. 2 f n", km, ret); return 0; } ____________________________ Результат на экране: km mile 2. 00 3. 71

Операторы цикла В большинстве языков программирования оператор цикла состоит из двух элементов - заголовка Операторы цикла В большинстве языков программирования оператор цикла состоит из двух элементов - заголовка и тела. Тело включает операторы, выполняемые в цикле, заголовок организует циклическое выполнение операторов тела. В соответствии с названием заголовок размещается непосредственно перед телом цикла. В языке С равноправно используются три разных оператора цикла, обозначаемых соответственно служебными словами while, for, do.

Цикл while (цикл с предусловием) Цикл while имеет вид: while (выражение_условие) тело_цикла Цикл while (цикл с предусловием) Цикл while имеет вид: while (выражение_условие) тело_цикла

Цикл while Программа пересчета км в морские мили. Вариант2 #include <stdio. h> #define M_MILE Цикл while Программа пересчета км в морские мили. Вариант2 #include #define M_MILE 1. 852 //1 морская миля -1852 m int main(void) { float ret, km=0. 5; printf("n km t mile n"); while(km<=10) { ret=km*(float)M_MILE; printf(" %4. 2 f t %4. 2 f n", km, ret); km+=0. 5; } return 0; }

Цикл do-while Цикл do (цикл с постусловием) имеет вид: do тело_цикла while (выражение_условие); Ложно Цикл do-while Цикл do (цикл с постусловием) имеет вид: do тело_цикла while (выражение_условие); Ложно (0)

Цикл do-while Фрагмент программы с использованием do-while beg=20000; do {k=KH_get_time(); /* KH_get_time() – функция Цикл do-while Фрагмент программы с использованием do-while beg=20000; do {k=KH_get_time(); /* KH_get_time() – функция возвращает текущее значение счетчика таймера*/ }while ( k > beg);

Цикл for (называемый параметрическим) имеет вид: for (выражение_1; выражение_условие; выражение_3) тело_цикла Первое и третье Цикл for (называемый параметрическим) имеет вид: for (выражение_1; выражение_условие; выражение_3) тело_цикла Первое и третье выражения в операторе for могут состоять из нескольких выражений, разделенных запятыми. Выражение_1 определяет действия, выполняемые до начала цикла, т. е. задает начальные условия для цикла; чаще всего это выражение присваивания.

Цикл for. Слайд 2 for (выражение_1; выражение_условие; выражение_3) тело_цикла Выражение_условие - обычно логическое или Цикл for. Слайд 2 for (выражение_1; выражение_условие; выражение_3) тело_цикла Выражение_условие - обычно логическое или арифметическое. Оно определяет условия окончания или продолжения цикла. Если оно истинно, то выполняется тело цикла, а затем вычисляется выражение_3. Выражение_3 обычно задает необходимые для следующей итерации изменения параметров или любых переменных тела цикла.

Схема организации цикла for Схема организации цикла for

Цикл for. Пример Фрагмент программы for(int i=0; i<10; i++) printf( Цикл for. Пример Фрагмент программы for(int i=0; i<10; i++) printf("%d %dn", i, 2*i+1);

Программа нахождения суммы первых членов ряда вида: 1 + 1/2 + 1/4 + 1/8 Программа нахождения суммы первых членов ряда вида: 1 + 1/2 + 1/4 + 1/8 + 1/16 #include #define LIMIT 15 main ( ) { int count; float sum, x; for(sum = 0. 0, x = 1. 0, count = 1; count <= LIMIT; count++, x *= 2. 0) { sum+=1. 0/x; printf(" sum = %f когда count = %dn" , sum, count); } return 0; }

Результат работы программы sum = 1. 000000 когда count = 1. sum = 1. Результат работы программы sum = 1. 000000 когда count = 1. sum = 1. 500000 когда count = 2. sum = 1. 750000 когда count = 3. sum = 1. 875000 когда count = 4. sum = 1. 937500 когда count = 5. sum = 1. 968750 когда count = 6. sum = 1. 984375 когда count = 7. sum = 1. 992188 когда count = 8. sum = 1. 996094 когда count = 9. sum = 1. 998047 когда count = 10. sum = 1. 999023 когда count = 11. sum = 1. 999512 когда count = 12. sum = 1. 999756 когда count = 13. sum = 1. 999878 когда count = 14. sum = 1. 999939 когда count = 15.

Оператор break используется в двух случаях. 1. В операторе switch с его помощью прерывается Оператор break используется в двух случаях. 1. В операторе switch с его помощью прерывается последовательности case. В этом случае break не передает управление за пределы блока. 2. Оператор break используется для немедленного прекращения выполнения цикла без проверки его условия, в этом случае оператор break передает управление оператору, следующему после оператора цикла.

Оператор выбора switch. Пример1 #include <stdio. h> int main(void ) { unsigned int fl; Оператор выбора switch. Пример1 #include int main(void ) { unsigned int fl; printf("fl="); scanf("%d", &fl); switch (fl) { case 0 : printf("Режим Контроль (test)n"); break; case 1 : printf("Режим Работа (work)n"); break; case 2 : printf("Режим Стенд (stand)n"); break; default: printf(" Неверно введен режим (err)n"); } return 0; }

Примеры использования оператора break Пример 1: for(int i=0; i<100; i++) {printf( Примеры использования оператора break Пример 1: for(int i=0; i<100; i++) {printf( "%d ", i); if(i==10) break; } Пример 2: i=0; for(; ; ) //бесконечный цикл { printf( "%d ", i); if(i==10) break; i++; }

Оператор continue o Оператор continue вызывает прерывание текущей итерации цикла и осуществляет переход к Оператор continue o Оператор continue вызывает прерывание текущей итерации цикла и осуществляет переход к следующей итерации. При этом все операторы до конца тела цикла пропускаются. o В цикле for оператор continue вызывает выполнение операторов приращения и проверки условия цикла. В циклах while и do-while оператор continue передает управление оператором проверки условий цикла.

Пример программы с оператором continue char done=0, ch; while(!done) { scanf( Пример программы с оператором continue char done=0, ch; while(!done) { scanf("%c", &ch); if(ch=='$') { done=1; continue; } printf("%c", ch+1); }

Какой цикл лучше? o Во-первых, решите, нужен ли вам цикл с предусловием(while, for) или Какой цикл лучше? o Во-первых, решите, нужен ли вам цикл с предусловием(while, for) или же с постусловием(do). o Циклы с предусловием имеют следующие преимущества: 1. Программу легче читать, если проверяемое условие находится в начале цикла. 2. Во многих случаях важно, чтобы тело цикла игнорировалось полностью, если условие вначале не выполняется

Когда лучше использовать while, а когда for? o Использование for представляется более предпочтительным в Когда лучше использовать while, а когда for? o Использование for представляется более предпочтительным в случае, когда в цикле используется инициализация и коррекция переменной, а применение цикла while - в случае, когда этого нет. o Поэтому использование цикла while вполне оправданно в случае while((ch != ‘$’) o Применение цикла for представляется более естественным в случаях, когда в циклах осуществляется счет прохождений с обновлением индекса: for (count = 1; count <= 100; count++)

Массивы o Массив – это набор переменных одного типа, имеющих одно и то же Массивы o Массив – это набор переменных одного типа, имеющих одно и то же имя. o В языке С все элементы одного массива располагаются в непрерывной области памяти. o Размер массива определяется во время компиляции и впоследствии остается неизменным. o Память, выделяемая под массив, имеет неопределенные значения. o Массивы могут быть одномерными и многомерными.

Одномерные массивы Общая форма объявления одномерного массива имеет следующий вид: тип имя_переменной[размер]; Например: double Одномерные массивы Общая форма объявления одномерного массива имеет следующий вид: тип имя_переменной[размер]; Например: double balance[100];

Одномерные массивы(слайд 2) При объявлении массив можно инициализировать значениями заключенными {}. Например: Математическая запись Одномерные массивы(слайд 2) При объявлении массив можно инициализировать значениями заключенными {}. Например: Математическая запись a=|1 2 3 4 5 6 7| Объявление массива с инициализацией в программе char a[7] ={1, 2, 3, 4, 5, 6, 7};

Размещение в памяти одномерного массива Э a[ a[ ле 0 м ] ен т Размещение в памяти одномерного массива Э a[ a[ ле 0 м ] ен т Зн 1 2 ач ен ие А 10 10 д 0 a[ a[ a[ 1 2 3 4 5 6 ] ] ] 3 4 5 6 7 10 10 10 0 0 0

Пример размещения массивов в памяти (слайд 1). Объявление массивов char study_dev[]= Пример размещения массивов в памяти (слайд 1). Объявление массивов char study_dev[]="dev/hda 1"; сhar study_mas 1[]={1, 2, 3, 4, 5, 6, 7, 8}; сhar study_mas 2[]={'1', '2', '3', '4', '5', '6', '7', '8'}; int study_mas_i[]={1, 2, 3, 4};

Пример размещения массивов в памяти (слайд 2) lkup Пример размещения массивов в памяти (слайд 2) lkup "study" study_dev, 0 x 80114670 study_mas 1, 0 x 80114680 study_mas 2, 0 x 80114688 study_mas_i, 0 x 80114690 -> dc 0 x 80114670 64 65 76 2 f 68 64 61 31 00 00 dev/hda 1. . . . 0 x 80114680 01 02 03 04 05 06 07 08 31 32 33 34 35 36 37 38. . . . 12345678 0 x 80114690 00 01 00 00 00 02 00 00 00 03 00 00 00 04. . . .

Одномерные массивы Объем памяти, необходимый для хранения массива определяется его типом и размером. Для Одномерные массивы Объем памяти, необходимый для хранения массива определяется его типом и размером. Для одномерного массива количество байт памяти вычисляется по формуле. количество_байт=sizeof(базовый_тип) * длина_массива Индекс первого элемента любого массива в языке С равна 0. Доступ к конкретному элементу массива осуществляется с помощью имени массива и индекса. Индекс элемента массива помещается в квадратных скобках после имени. balance[3]=12. 23;

Программа с использованием одномерного массива #include <stdio. h> #define MONTH 12 int main(void) { Программа с использованием одномерного массива #include #define MONTH 12 int main(void) { int days[MONTH]={31, 28, 31, 30, 31, 30, 31}; for(int i=0; i

Двухмерные массивы Простейшая форма многомерного массива – двухмерный массив. Объявление двухмерного массива d размером Двухмерные массивы Простейшая форма многомерного массива – двухмерный массив. Объявление двухмерного массива d размером 10 x 20 выглядит следующим образом: int d[10][20]; Первый индекс указывает номер строки, второй – номер столбца. Инициализация s[2][3]= Результат инициализации: { 5 6 0 {5, 6}, 7 8 0 {7, 8} };

Двухмерные массивы (слайд 2) Обращение: d[0][2]=100; Для двуxмерного массива количество байт памяти вычисляется по Двухмерные массивы (слайд 2) Обращение: d[0][2]=100; Для двуxмерного массива количество байт памяти вычисляется по формуле. количество_байт=размер_1 -го_измерения * размер_2 -го_измерения * sizeof(базовый_тип)

Размещение в памяти двухмерного массива int study_mas[3][4]={{1, 2, 3, 4}, {5, 6, 7, 8}, Размещение в памяти двухмерного массива int study_mas[3][4]={{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 0 xa, 0 xb, 0 xc}}; -> lkup "study" study_mas, 0 x 80114650, gi -> di 0 x 80114650 0 x 80114660 0 x 80114670 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008 00000009 0000000 a 0000000 b 0000000 c

Многомерные массивы В языке C можно пользоваться массивами, размерность, которых больше двух. Общая форма Многомерные массивы В языке C можно пользоваться массивами, размерность, которых больше двух. Общая форма объявления многомерного массива следующая: тип имя_массива [Размер1] [Размер2]… [Размер. N]; При обращении к многомерным массивам компьютер много времени затрачивает на вычисление адреса, поэтому доступ к элементам многомерного массива происходит значительно медленнее, чем к элементам одномерного.

Вложенные циклы В теле цикла разрешены любые исполнимые операторы, в том числе и циклы, Вложенные циклы В теле цикла разрешены любые исполнимые операторы, в том числе и циклы, т. е. можно конструировать вложенные циклы. Задание Написать программу подсчета суммы всех строк элементов матрицы: |1 23 4 | |2 24 5 | Вывести результат на экран.

Программа с вложенными циклами #include <stdio. h> #define STR 2 #define COL 3 int Программа с вложенными циклами #include #define STR 2 #define COL 3 int main(void) { int mas[STR][COL]={{1, 23, 4}, {2, 24, 5}}; int i, j, total_str; for(i=0; i

Работа с адресами 0 x 80114670 64 65 76 2 f 68 64 61 Работа с адресами 0 x 80114670 64 65 76 2 f 68 64 61 31 00 00 0 x 80114680 01 02 03 04 05 06 07 08 31 32 33 34 35 36 37 38 0 x 80114690 00 01 00 00 00 02 00 00 00 03 00 00 00 04 mi 0 x 8011469 c, 0 xffff 0 x 8004 e 9 c 0 -> dc 0 x 80114670 64 65 76 2 f 68 64 61 31 00 00 0 x 80114680 01 02 03 04 05 06 07 08 31 32 33 34 35 36 37 38 0 x 80114690 00 01 00 00 00 02 00 00 00 03 ff ff

Пример составления программы в машинных кодах Составим программу вычисления одного значения функции: при A Пример составления программы в машинных кодах Составим программу вычисления одного значения функции: при A = 3; x = 4; B = 5 для гипотетической одноадресной ЭВМ Пусть ЭВМ имеет следующую систему команд. Дес. № Операция Дв. п. п. ССЧ 1 Пересылка содержимого ячейки ОЗУ в АЛУ 1 0001 2 Пересылка результата операции из АЛУ в ОЗУ 2 0010 3 Сложение 3 0011 4 Умножение 4 0100 5 Стоп 5 0101

Пример составления программы в машинных кодах (слайд 2) Адрес ячейки ОЗУ Команда КОП Адрес Пример составления программы в машинных кодах (слайд 2) Адрес ячейки ОЗУ Команда КОП Адрес 0 1 5 1 4 6 2 3 7 3 2 8 4 5 Комментарий Пересылка числа А из ячейки 5 в АЛУ Умножение числа А на x из ячейки 6 Сложение результата с числом В из яч. 7 Пересылка результата в яч. 8 ОЗУ Стоп 5 3 А 6 4 x 7 5 В 8 17 y

Указатель — это адрес объекта в памяти. m Адрес ячейки Значение переменной в памяти Указатель — это адрес объекта в памяти. m Адрес ячейки Значение переменной в памяти 0 x 80114670 0 x 80114680 0 x 801146 a 0 0 x 80114690 count 0 x 801146 a 0 0 x 00012030 0 x 801146 b 0 Одна переменная ссылается на другую

Указательные переменные Переменную, являющуюся указателем, нужно соответствующим образом объявить. Объявление указателя состоит из имени Указательные переменные Переменную, являющуюся указателем, нужно соответствующим образом объявить. Объявление указателя состоит из имени типа, символа * и имени переменной. Общая форма объявления указателя следующая: тип *имя; Здесь тип — это базовый тип указателя, им может быть любой правильный тип. Имя определяет имя переменной-указателя. Например: int *adr;

Указательные переменные (слайд 2) Фактически указатель любого типа может ссылаться на любое место в Указательные переменные (слайд 2) Фактически указатель любого типа может ссылаться на любое место в памяти. Однако выполняемые с указателем операции существенно зависят от его типа. Например, если объявлен указатель типа int *, компилятор предполагает, что любой адрес, на который он ссылается, содержит переменную типа int, хоть это может быть и не так. Следовательно, объявляя указатель, необходимо убедиться, что его тип совместим с типом объекта, на который он будет ссылаться.

Операции для работы с указателями. 1. Оператор &, возвращающий адрес операнда в памяти. Это Операции для работы с указателями. 1. Оператор &, возвращающий адрес операнда в памяти. Это унарный оператор. Приоритет – 2 ранга. Например, оператор m = &count; записывает в переменную m адрес переменной count. Этот адрес представляет собой адрес ячейки памяти компьютера, в которой размещена переменная. Выражение "&переменная" означает "адрес переменной". Следовательно, инструкция m = &scount; означает: "Переменной m присвоить адрес, по которому расположена переменная count; ".

Пример работы с указателями #include <stdio. h> int study_m=1; int *study_n; void start(void) { Пример работы с указателями #include int study_m=1; int *study_n; void start(void) { study_n=&study_m; printf("nstudy_n=%p", study_n); return; }

Пример работы с указателями (слайд 2) study_n=&study_m; lkup Пример работы с указателями (слайд 2) study_n=&study_m; lkup "study" study_m, 0 x 80138 de 8 study_n, 0 x 80138 dec -> di 0 x 80138 de 8 m n 0 x 80138 de 8 00000001 00000000 -> start study_n=0 x 80138 de 8 -> di 0 x 80138 de 8 00000001 80138 de 8 00000000 ->

Оператор * возвращает значение объекта, расположенного по указанному адресу Это унарный оператор. Приоритет – Оператор * возвращает значение объекта, расположенного по указанному адресу Это унарный оператор. Приоритет – 2 ранга. Оператор * возвращает значение объекта, расположенного по указанному адресу. Операндом для * служит адрес объекта (переменной).

Оператор * (слайд 2) study_n=&study_m; Например, если переменная study_n содержит адрес переменной study_m, то Оператор * (слайд 2) study_n=&study_m; Например, если переменная study_n содержит адрес переменной study_m, то оператор: q = *study_n; записывает значение переменной study_m в переменную q. Наш фрагмент программы можно прочесть как "q получает значение, расположенное по адресу study_n ".

Объявление указателей Если переменная является указателем, то в объявлении перед ее именем нужно поставить Объявление указателей Если переменная является указателем, то в объявлении перед ее именем нужно поставить символ *, он сообщит компилятору о том, что это указатель на переменную данного типа. Например, объявление указателя на переменную типа char записывается так: char *ch; int x, *ch, count;

Объявление указателей (слайд 2) Тип данных, на который указывает указатель, называется базовым типом указателя. Объявление указателей (слайд 2) Тип данных, на который указывает указатель, называется базовым типом указателя. Сам указатель является переменной, содержащей адрес объекта базового типа. Компилятор учтет размер указателя в архитектуре компьютера и выделит для него необходимое количество байтов, чтобы в указатель поместился адрес. Базовый тип указателя определяет тип объекта, хранящегося по этому адресу.

Пример работы с указателями #include <stdio. h> int main(void) { int target, source; int Пример работы с указателями #include int main(void) { int target, source; int *m; source = 10; m = &source; target = *m; printf("%d", target); return 0; } Результат на экране 10

Присваивание указателей Указатель можно использовать в правой части оператора присваивания для присваивания его значения Присваивание указателей Указатель можно использовать в правой части оператора присваивания для присваивания его значения другому указателю. Если оба указателя имеют один и тот же тип, то выполняется простое присваивание, без преобразования типа.

Пример присваивания указателей #include <stdio. h> int main(void) { int x = 99; int Пример присваивания указателей #include int main(void) { int x = 99; int *p 1, *p 2; p 1 = &x; p 2 = p 1; /* печать значение x дважды */ printf("Значение по адресу p 1 и p 2: %d %dn", *p 1, *p 2); /* печать адреса x дважды */ printf("Значение указателей p 1 и p 2: %p %p", p 1, p 2); return 0; }

Преобразование типа указателя o Указатель можно преобразовать к другому типу. Эти преобразования бывают двух Преобразование типа указателя o Указатель можно преобразовать к другому типу. Эти преобразования бывают двух видов: с использованием указателя типа void * и без его использования. o Тип указателя void * используется, если тип объекта неизвестен. Он полезен для ссылки на произвольный участок памяти, независимо от размещенных там объектов. o В языке С допускается присваивание указателя типа void * указателю любого другого типа (и наоборот) без явного преобразования типа указателя.

Пример преобразования с ошибкой #include <stdio. h> int main(void) { double x = 100. Пример преобразования с ошибкой #include int main(void) { double x = 100. 1, y; int *p; /* В следующем операторе указателю на целое p (присваивается значение, ссылающееся на double. */ p = (int *) &x; //ошибка /* Следующий оператор работает не так, как ожидается. */ y = *p; /* Следующий оператор не выведет число 100. 1. */ printf("Значение x равно: %f (Это не так!)", y); return 0; }

Пример работы с указателями из ПО приборов НК. Необходимо посчитать контрольную сумму области памяти, Пример работы с указателями из ПО приборов НК. Необходимо посчитать контрольную сумму области памяти, начиная с адреса 0 xa 8400030. Размер области (в байтах) находится по адресу 0 xa 8400004 и на размер отведено 4 байт. адрес значение 0 xa 8400004 0 x 00177579 0 xa 8400030 Контроли руемая область памяти 0 xa 8400030+0 x 0 0177579

Пример работы с указателями из ПО приборов НК (слайд 2) #define KH__ADR_OC #define KH__ADR_KC Пример работы с указателями из ПО приборов НК (слайд 2) #define KH__ADR_OC #define KH__ADR_KC 0 xa 8400030 0 xa 8400004 int flash(void) { unsigned char *p; unsigned int i, ks, kc_flash; kc_flash=*(unsigned int *)KH__ADR_KC; //размер области памяти в байтах for ( ks=i=0, p=(unsigned char *)KH__ADR_OC ; i

Инициализация указателей o После объявления указателя до первого присвоения он содержит неопределенное значение. o Инициализация указателей o После объявления указателя до первого присвоения он содержит неопределенное значение. o Если попытаться использовать указатель перед присвоением ему нужного значения, то скорее всего он мгновенно разрушит программу или всю операционную систему.

Инициализация указателей (слайд 2) o При работе с указателями большинство программистов придерживаются следующего важного Инициализация указателей (слайд 2) o При работе с указателями большинство программистов придерживаются следующего важного соглашения: указатель, не ссылающийся в текущий момент времени должным образом на конкретный объект, должен содержать нулевое значение. o Нуль используется потому, что С гарантирует отсутствие чего-либо по нулевому адресу. o Следовательно, если указатель равен нулю, то это значит, во-первых, что он ни на что не ссылается, а во-вторых — что его сейчас нельзя использовать.

Инициализация указателей (слайд 3) o Указателю можно задать нулевое значение, присвоив ему 0. Например, Инициализация указателей (слайд 3) o Указателю можно задать нулевое значение, присвоив ему 0. Например, следующий оператор инициализирует р нулем: char *p = 0; o Дополнительно к этому во многих заголовочных файлах языка С, например, в определен макрос NULL, являющийся нулевой указательной константой. Поэтому в программах на С часто можно увидеть следующее присваивание: char *p = NULL;

Указатели и массивы Если в программе пишется имя массива без индекса, то это означает Указатели и массивы Если в программе пишется имя массива без индекса, то это означает адрес нулевого элемента массива. Пример: char str[80], *p 1; p 1 = str; Здесь p 1 указывает на нулевой элемент массива str. Обратиться к пятому элементу массива str можно с помощью любого из двух выражений: str[4] * (p 1+4)

Обращение к элементам массива В языке С существуют два метода обращения к элементу массива: Обращение к элементам массива В языке С существуют два метода обращения к элементу массива: 1. Адресная арифметика. Пример: * (p 1+4) 2. Индексация массива. Пример: str[4] Стандартная запись массивов с индексами наглядна и удобна в использовании, однако с помощью адресной арифметики иногда существенно удается сократить время доступа к элементам массива. Поэтому адресная арифметика часто используется в программах, где существенную роль играет быстродействие.

/*Программа нахождения max элемента в массиве 1 вариант*/ #include <stdio. h> int main(void) { /*Программа нахождения max элемента в массиве 1 вариант*/ #include int main(void) { int mas[4], max; for (int i=0; imax) max= mas[i] ; } printf("n!!! max=%d n", max); return 0; }

/*Программа нахождения max элемента в массиве 2 вариант*/ #include <stdio. h> int main(void) { /*Программа нахождения max элемента в массиве 2 вариант*/ #include int main(void) { int mas[4], max; for (int i=0; imax) max=*(mas+i); } printf("n!!! max=%d n", max); return 0; }

Указатели и строковые константы char *p = Указатели и строковые константы char *p = "тестовая строка"; Переменная р является указателем, а не массивом. Компилятор создает так называемую таблицу строк, в ней он сохраняет строковые константы, которые встречаются ему по ходу чтения текста программы. Следовательно, когда встречается объявление с инициализацией, компилятор сохраняет строку "тестовая строка" в таблице строк, а в указатель p записывает ее адрес. Дальше в программе указатель p может быть использован как любая другая строка.

Пример работы со строковыми константами #include <stdio. h> #include <string. h> char *p = Пример работы со строковыми константами #include #include char *p = "тестовая строка"; int main(void) { int t; /* печать строки слева направо и справа налево */ printf(p); for(t=15; t>-1; t--) {printf("%c", p[t]); } return 0; }

Массивы указателей Указатели могут быть собраны в массив. В следующем операторе объявлен массив из Массивы указателей Указатели могут быть собраны в массив. В следующем операторе объявлен массив из 10 указателей на объекты типа int: int *x[10]; Для присвоения, например, адреса переменной var третьему элементу массива указателей, необходимо написать: x[2] = &var;

Пример работы с массивами указателей void syntax_error(int num) { char *err[] = { Пример работы с массивами указателей void syntax_error(int num) { char *err[] = { "Нельзя открыть файлn", "Ошибка при чтенииn", "Ошибка при записиn", "Некачественный носительn" }; printf("%s", err[num]); }

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

Объявление структуры (слайд 1) Ключевое слово struct сообщает компилятору, что объявляется структура. Например: struct Объявление структуры (слайд 1) Ключевое слово struct сообщает компилятору, что объявляется структура. Например: struct t_student { char surname[30]; char name[20]; float mark; }; //фамилия //имя //балл

Объявление структуры (слайд 2) o Объявление структура на самом деле никакая переменная не создается. Объявление структуры (слайд 2) o Объявление структура на самом деле никакая переменная не создается. Определяется вид данных. o Когда объявляется структура, то определяется тип, а не переменная. Физическая память под структуру не отводится. o Объявление переменной типа t_student: struct t_student;

Расположение в памяти структуры Когда объявляется переменная-структура, компилятор автоматически выделяет количество памяти, достаточное, чтобы Расположение в памяти структуры Когда объявляется переменная-структура, компилятор автоматически выделяет количество памяти, достаточное, чтобы разместить все ее члены (поля). Элемент Кол-во байт surname (фамилия) name (имя) mark (балл) 30 20 4

Одновременное объявление структуры и нескольких переменных 1 вариант с указанием типа (тега) struct t_student Одновременное объявление структуры и нескольких переменных 1 вариант с указанием типа (тега) struct t_student { char surname[30]; //фамилия char name[20]; //имя float mark; //балл }student, entrant; /*студент, абитуриент*/ struct { 2 вариант char surname[30]; //фамилия char name[20]; //имя float mark; //балл }student, entrant; /*студент, абитуриент*/

Доступ к членам структуры o Доступ к отдельным членам структуры осуществляется с помощью оператора. Доступ к членам структуры o Доступ к отдельным членам структуры осуществляется с помощью оператора. Этот оператор обычно называют оператором точка или оператором доступа к члену структуры. Ранг оператора точка – 1. Общий вид оператора точка: имя-объекта. имя-члена Например: student. mark = 4. 5; entrant. mark = 4. 4;

Пример работы со структурой #include <stdio. h> int main(void) { int t; struct { Пример работы со структурой #include int main(void) { int t; struct { char surname[30]; //фамилия char name[20]; //имя float mark; //балл }student= {"Ivanova", "Ann", 4. 3}; printf("n"); for(t=0; student. name[t]; t++) {printf("%c", student. name[t]); } printf("n"); return 0; }

Указатели на структуры. Объявление указателя на структуру struct t_student *student; Чтобы получить адрес переменной-структуры, Указатели на структуры. Объявление указателя на структуру struct t_student *student; Чтобы получить адрес переменной-структуры, необходимо перед ее именем поместить оператор &. Фрагмент кода: struct t_student { char surname[30]; //фамилия char name[20]; //имя float mark; //балл }student; struct t_student *p; /* объявление указателя на структуру */ /*адрес структуры student можно присвоить указателю p: */ p = &student;

Доступ к члену структуры o Чтобы с помощью указателя на структуру получить доступ к Доступ к члену структуры o Чтобы с помощью указателя на структуру получить доступ к ее членам, необходимо использовать оператор стрелка ->. Например: p->name o Оператор ->, который обычно называют оператором стрелки, состоит из знака "минус", за которым следует знак "больше". Стрелка применяется вместо оператора точки тогда, когда для доступа к члену структуры используется указатель на структуру

#include <stdio. h> int main(void) { int t; struct t_student { char surname[30]; char #include int main(void) { int t; struct t_student { char surname[30]; char name[20]; float mark; }student= {"Ivanova", "Ann", 4. 3}; struct t_student *p; p=&student; for(t=0; p->name[t]; t++) {printf("%c", p->name[t]); } printf("n"); return 0; }

Массивы структур struct t_student { char surname[30]; //фамилия char name[20]; //имя float mark; //балл Массивы структур struct t_student { char surname[30]; //фамилия char name[20]; //имя float mark; //балл }student[2]={ {"Ivanova", "Ann", 4. 3}, {"Petrov", "Victor", 4. 4} }; Доступ к элементу: student[0]. mark; student[1]. name[0];

Структура функции на языке С заголовок Директива препроцессора #include <stdio. h> main() Имя функции Структура функции на языке С заголовок Директива препроцессора #include main() Имя функции с аргументами тело int A, x, B, y; A=3; x=4; B=5; y=A*x+B; printf("y=%d", y); Оператор описания Операторы присваивания Операторы вызова функции Структура функции в языке и: заголовок и тело.

Структура программы на языке Си Си-программа Функция, с которой начинается выполнение программы #Заголовок main() Структура программы на языке Си Си-программа Функция, с которой начинается выполнение программы #Заголовок main() Операторы функция N Функции – это строительные блоки языка Си Операторы Функции состоят из операторов функция M Операторы Структура программы

Функции Общий вид функции o В общем виде функция выглядит следующим образом: возвращаемый-тип имя-функции Функции Общий вид функции o В общем виде функция выглядит следующим образом: возвращаемый-тип имя-функции (список формальных параметров) { тело функции } Пример: int main(void) { <текст функции> return 0; }

Заголовок функции o Возвращаемое значение и список формальных параметров нужен для связи с другими Заголовок функции o Возвращаемое значение и список формальных параметров нужен для связи с другими функциями. o Функция может возвращать любой тип данных, за исключением массивов. o Список формальных параметров — это список, элементы которого отделяются друг от друга запятыми. Каждый такой элемент состоит из имени переменной и ее типа данных. o Функция может быть и без параметров, тогда их список будет пустым. Такой пустой список можно указать в явном виде, поместив для этого внутри скобок ключевое слово void. o Примеры: void f(int i, int k, int j) int main(void) void print_mas(void)

Пример описания, определения и вызова функции float min(float; float); /*описание функции с двумя формальными Пример описания, определения и вызова функции float min(float; float); /*описание функции с двумя формальными параметрами типа float и возвращаемым значением типа float*/ float min(float a, float b) /*определение функции*/ { if(a

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

Примеры стандартных функций Функция strlen #include <string. h> size_t strlen(const char *str); Функция strlen() Примеры стандартных функций Функция strlen #include size_t strlen(const char *str); Функция strlen() возвращает длину строки, адресуемой параметром str. Символ конца строки (‘ 0’) не учитывается. Пример: char str[]="HELLO"; size_t len; len=strlen(str); printf("n len=%dn", len); Результат работы программы: len=5

Примеры стандартных функций. Функция memset #include <string. h> void *memset(void *buf, int ch, size_t Примеры стандартных функций. Функция memset #include void *memset(void *buf, int ch, size_t count); Функция memset копирует параметр ch в первые count символов массива buf. Функция возвращает значение указателя buf. Пример: //фрагмент программы char buf[1024]; memset(buf, 0, sizeof(buf)); /* функция копирует 0 во все элементы массива buf */

Область действия переменных o Объявление переменных может быть расположено в трех местах: 1. внутри Область действия переменных o Объявление переменных может быть расположено в трех местах: 1. внутри функции (локальные переменные); 2. вне всех функций (глобальные переменные); 3. в определении параметров функции (формальные параметры функций);

Локальные переменные (слайд 1) o Переменные, объявленные внутри функций, называются локальными переменными. o Локальную Локальные переменные (слайд 1) o Переменные, объявленные внутри функций, называются локальными переменными. o Локальную переменную можно использовать только внутри блока, в котором она объявлена. o Локальная переменная невидима за пределами своего блока. o Блок программы — это описания и инструкции, объединенные в одну конструкцию путем заключения их в фигурные скобки.

Локальные переменные (слайд 2) Локальные переменные существуют только во время выполнения программного блока, в Локальные переменные (слайд 2) Локальные переменные существуют только во время выполнения программного блока, в котором они объявлены, создаются они при входе в блок, а разрушаются — при выходе из него. Пример: void func 1(void) void func 2(void) { { int x; x = 10; x = -199; } }

Глобальные переменные o Глобальные переменные видимы и могут использоваться в любом месте программы. o Глобальные переменные o Глобальные переменные видимы и могут использоваться в любом месте программы. o Глобальные переменные сохраняют свое значение на протяжении всей работы программы. o Чтобы создать глобальную переменную, ее необходимо объявить за пределами функции. o Глобальная переменная может быть использована в любом выражении, независимо от того, в каком блоке это выражение используется.

Глобальные переменные. Пример #include <stdio. h> int count; /* глобальная переменная count */ int Глобальные переменные. Пример #include int count; /* глобальная переменная count */ int main(void) { count = 100; func 1(); return 0; } void func 1(void) { int temp; temp = count; printf("count равно %d", count); /* напечатает 100 */}

Пример создания программы с несколькими функциями. Функция main int main(void ) { float list Пример создания программы с несколькими функциями. Функция main int main(void ) { float list [50]; readlist(list); sort(list); if(calc(list)==1) print_res(list); результат*/ return 0; } //вводит набор чисел //сортирует числа //вычисляет по формулам /*выводит на печать

Пример создания программы с несколькими функциями. Описание функций void readlist(float *); //вводит набор чисел Пример создания программы с несколькими функциями. Описание функций void readlist(float *); //вводит набор чисел void sort (float *); //сортирует числа int calc(float *); //вычисляет по формулам void print_res(float *); /*выводит на печать результат*/ Запишем описание функций в библиотечный файл с именем func. h

Пример создания программы с несколькими функциями. Функция main c включением библиотечного файла #include Пример создания программы с несколькими функциями. Функция main c включением библиотечного файла #include "func. h” int main(void ) { float list [50]; readlist(list); sort(list); if(calc(list)==1) print_res(list); результат*/ return 0; } //вводит набор чисел //сортирует числа //вычисляет по формулам /*выводит на печать

Пример создания программы с несколькими функциями. Определение функций void readlist(float *) //вводит набор чисел Пример создания программы с несколькими функциями. Определение функций void readlist(float *) //вводит набор чисел {} void sort (float *) {} //сортирует числа int calc(float *) //вычисляет по формулам {return 0; } void print_res(float *); /*выводит на печать результат*/ {}