
- •Происхождение языка с
- •Язык среднего уровня
- •Структурированный язык
- •Язык программирования
- •Компиляторы против интерпретаторов
- •Вид программ на с
- •Библиотеки и компоновка
- •Раздельная компиляция
- •Карта памяти с-программы
- •Переменные, константы, операторы и выражения
- •Идентификаторы
- •Типы данных
- •Модификаторы типов
- •Модификаторы доступа
- •Объявление переменных
- •Локальные переменные
- •Формальные параметры
- •Глобальные переменные
- •Спецификаторы хранения
- •Статические переменные
- •Статические локальные переменные
- •Статические глобальные переменные
- •Регистровые переменные
- •Оператор присваивания
- •Многочисленное присваивание
- •Преобразование типов при присваивании
- •Инициализация переменных
- •Константы
- •Символьные константы с обратным слэшем
- •Операторы
- •Арифметические операторы
- •Увеличение и уменьшение
- •Операторы отношения и логические операторы
- •Битовые операторы
- •Оператор ?
- •Операторы указания & и *
- •Оператор sizeof
- •Оператор «запятая»
- •Операторы [ ] u ()
- •Приоритеты в с
- •Выражения
- •Преобразование типов в выражениях
- •Принудительные преобразования
- •Пробелы и круглые скобки
- •Сокращенные операторы в с
- •Операторы управления программой
- •Истина и ложь в с
- •Операторы выбора
- •Вложенные if
- •Лесенка if-else-if
- •Оператор ?
- •Вложенные операторы switch
- •Вариации цикла for
- •Бесконечный цикл
- •Циклы for без тела
- •Метки и goto
- •Функции
- •Оператор return
- •Выход из функции
- •Возвращаемые значения
- •Значения, возвращаемые функцией main()
- •Правила видимости для функций
- •Аргументы функции
- •Передача по значению и передача по ссылке
- •Создание передачи по ссылке
- •Передача массивов в функции
- •Аргументы функции main()
- •Функции, возвращающие нецелые значения
- •Использование прототипов функции
- •Прототипы стандартных библиотечных функций
- •Создание прототипов функций, не имеющих параметров
- •Возврат указателей
- •Рекурсия
- •Сопоставление классического и современного объявления параметров
- •Указатели на функции
- •Особенности реализации
- •Параметризированные функции и функции общего назначения
- •Эффективность
- •Массивы
- •Одномерный массив
- •Создание указателя на массив
- •Передача одномерных массивов в функции
- •Двумерные массивы
- •Массивы строк
- •Многомерные массивы
- •Индексация с помощью указателей
- •Размещение массивов
- •Инициализация массива
- •Инициализация безразмерных массивов
- •Пример программы игры в крестики-нолики
- •Указатели
- •Указатели - это адреса
- •Переменные-указатели
- •Операторы для работы с указателями
- •Выражения с указателями
- •Присваивание указателей
- •Арифметические действия с указателями
- •Сравнение указателей
- •Динамическое выделение и указатели
- •Указатели на константы
- •Указатели на константы
- •Указатели на константы
- •Указатели и массивы
- •Указатели на символьные массивы
- •Массивы указателей
- •Указатели на указатели - многочисленное перенаправление
- •Инициализация указателей
- •Указатели на функции
- •Проблемы, связанные с указателями
- •Структуры, объединения и определяемые пользователем типы
- •Структуры
- •Доступ к членам структуры
- •Присваивание структур
- •Массивы структур
- •Программа инвентаризации
- •Передача структур в функции
- •Передача членов структур в функции
- •Передача всей структуры в функцию
- •Указатели на структуры
- •Объявление указателя на структуру
- •Использование указателей на структуру
- •Массивы и структуры в структурах
- •Битовые поля
- •Объединения
- •Перечисления
- •Использование sizeof для обеспечения переносимости
- •Ввод, вывод, потоки и файлы
- •Потоки и файлы
- •Текстовые потоки
- •Двоичные потоки
- •Консольный ввод/вывод
- •Чтение и запись символов
- •Чтение и запись строк: gets() и puts()
- •Форматированный консольный ввод/вывод
- •Печать символов
- •Вывод чисел
- •Вывод адресов
- •Спецификатор %n
- •Модификаторы формата
- •Спецификатор минимума ширины поля
- •Спецификатор точности
- •Выровненный вывод
- •Работа с другими типами данных
- •Модификаторы * u #
- •Спецификаторы формата
- •Ввод чисел
- •Ввод беззнаковых целых
- •Чтение отдельных символов с помощью scanf()
- •Чтение строк
- •Ввод адреса
- •Спецификатор %n
- •Использование множества сканирования
- •Пропуск нежелательных специальных символов
- •Обычные символы в управляющей строке
- •В scanf() следует передавать адреса
- •Модификаторы формата
- •Подавление ввода
- •Файловая система ansi с
- •Указатель на файл
- •Открытие файла
- •Запись символа
- •Чтение символа
- •Использование fopen(), getc(), putc() и fclose()
- •Использование feof()
- •Две расширенные функции: getw() и putw()
- •Работа со строками: fgets() и fputs()
- •Fseek() и произвольный доступ
- •Удаление файлов
- •Работа с консолью
- •Препроцессор и комментарии
- •Директивы условной компиляции
- •Использование defined
- •Операторы препроцессора # и ##
- •Предопределенные макросы
- •Комментарии
Операторы [ ] u ()
В С круглые скобки предназначены для изменения приоритета выполнения операторов.
Квадратные скобки предназначены для индексации массивов . Короче говоря, если имеется массив, то с помощью квадратных скобок можно обратиться к элементу массива. Например, в программе #include <stdio.h> char s[80]; int main(void) { s[3] = 'X'; printf("%c", s [3]); return 0; } сначала присваивается значение 'X' четвертому элементу (надо помнить, что индексация массивов в С начинается с 0) массива s, а затем печатается этот элемент.
Приоритеты в с
Таблица: Приоритеты операторов |
|
Высший |
() [] -> ! ~ + - ++ -- & * size(тип) * / % + - (бинарные) << >> < <= > >= == != & ^ | && || ?: = *= /= %= += -= &= ^= |= <<= >>= |
Низший |
, |
Таблица содержит приоритеты всех операторов в С. Следует обратить внимание, что все операторы, кроме унарных операторов и оператора ?, вычисляются слева направо. Унарные операторы (*, &, -) и оператор ? вычисляются справа налево.
Выражения
Операторы, константы и переменные являются составными частями выражений. Выражения в С это любая допустимая комбинация этих частей. Поскольку большинство выражений подчиняется стандартным правилам алгебры, они, как правило, используются в соответствии с данными правилами. Тем не менее, имеются некоторые аспекты выражений, характерных для С.
Преобразование типов в выражениях
Когда переменные и константы различных типов смешиваются в выражениях, то происходит преобразование к одному типу. Компилятор преобразует все операнды «вверх», к типу большего операнда. Ниже описываются правила преобразования типов.
Все переменные типа char и short int преобразуются к типу int. Все переменные типа float преобразуются к типу double.
Если один из пары операндов имеет тип long double, другой операнд также преобразуется к long double. Иначе если один из операндов имеет тип double, другой операнд также преобразуется к double. Иначе если один из операндов имеет тип long, другой операнд также преобразуется к long, Иначе если один из операндов имеет тип unsigned, другой операнд также преобразуется к unsigned.
В результате применения этих правил преобразования каждая пара операндов будет иметь одинаковый тип и результат каждой операции будет совпадать по типу с операндами. Заметим, что второе правило имеет несколько условий, которые должны применяться последовательно. Например, рассмотрим преобразование типов, показанное ниже.
Пример преобразования типов |
|
Сначала символ ch преобразуется к целому, а вещественная переменная с одинарной точностью f преобразуется к double. Затем ch / i преобразуется к double, поскольку f * d имеет тип double. Конечный результат имеет тип double, поскольку оба операнда типа double.
Принудительные преобразования
Имеется возможность заставить выражение принять определенный тип с помощью оператора принудительных преобразований. Эта операция имеет следующий вид: (тип) выражение где тип - это один из стандартных типов данных С или определяемый пользователем тип. Например, если необходимо, чтобы выражение х / 2 имело тип float (остаток сохранится), следует написать: (float) х / 2
Оператор принудительных преобразований - это унарный оператор, имеющий такой же приоритет, как и остальные унарные операторы.
Хотя принудительные преобразования редко используются при программировании на С, бывают случаи, когда они просто необходимы. Например, необходимо использовать целое число для управления циклом и, кроме этого, требуется вычислять дробную часть от деления этого числа на какое-либо другое, как в следующем примере: #include <stdio.h> /* выводит i и i/2 с дробной частью */ int main (void) { int i; for(i=1; i<=100; ++i ) printf ("%d / 2 is: %f\n", i, (float) i/2); return 0; } Без принудительного преобразования (float) будет вычисляться только целая часть, а благодаря (float) получим также и дробную часть.