
- •Происхождение языка с
- •Язык среднего уровня
- •Структурированный язык
- •Язык программирования
- •Компиляторы против интерпретаторов
- •Вид программ на с
- •Библиотеки и компоновка
- •Раздельная компиляция
- •Карта памяти с-программы
- •Переменные, константы, операторы и выражения
- •Идентификаторы
- •Типы данных
- •Модификаторы типов
- •Модификаторы доступа
- •Объявление переменных
- •Локальные переменные
- •Формальные параметры
- •Глобальные переменные
- •Спецификаторы хранения
- •Статические переменные
- •Статические локальные переменные
- •Статические глобальные переменные
- •Регистровые переменные
- •Оператор присваивания
- •Многочисленное присваивание
- •Преобразование типов при присваивании
- •Инициализация переменных
- •Константы
- •Символьные константы с обратным слэшем
- •Операторы
- •Арифметические операторы
- •Увеличение и уменьшение
- •Операторы отношения и логические операторы
- •Битовые операторы
- •Оператор ?
- •Операторы указания & и *
- •Оператор 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
- •Операторы препроцессора # и ##
- •Предопределенные макросы
- •Комментарии
Оператор ?
С имеет очень мощный оператор, который можно использовать вместо структуры if-then-else. Оператор ? имеет следующий вид:
выражение1 ? выражение2 : выражение3 где выражение1, выражение2 и выражениеЗ - это выражения.
Оператор ? работает следующим образом: вычисляется выражение1; если оно истинно, то вычисляется выражение2 и все выражение получает это значение; а если оно ложно, то вычисляется выражение3 и все выражение получает это значение. Например: х = 10; у = х > 9 ? 100 : 200; В данном примере у получает значение 100. Если бы х было меньше, чем 9, то у получило бы значение 200. Ниже приведен фрагмент программы, выполняющий такие же действия, но с использованием операторов if/else: х = 10; if (х > 9) у = 100; else у = 200;
Операторы указания & и *
Указатель - это адрес переменной в памяти. Указатель на переменную - это переменная, специально созданная для хранения указателя на объект определенного типа. Зная адрес переменной, можно существенно упростить работу некоторых программ. Указатели имеют три главных назначения в С:
Предоставляют быстрое обращение к элементам массива.
Позволяют функциям модифицировать передаваемые параметры.
Поддерживают динамические структуры данных, например списки.
Оператор &. Это унарный оператор, возвращающий адрес операнда в памяти. (Унарному оператору требуется только один операнд.) Например: m = &count; помещает в m адрес переменной count. Это адрес внутреннего местоположения переменной в компьютере. С самим значением переменной ничего не делается. Оператор & можно запомнить как «взятие адреса». Поэтому вышеупомянутый оператор присваивания можно прочитать как «m получает адрес count».
Для лучшего понимания данного присваивания предположим, что переменная count находится по адресу 2000. Также предположим, что count имеет значение 100. После данного присваивания m будет содержать 2000.
Оператор *, дополняющий &. Это унарный оператор, возвращающий значение переменной по указанному адресу. Например: если m содержит адрес переменной count, то q = *m; помещает значение count в q. Следуя вышеприведенному примеру, q получит значение 100, поскольку 100 хранилось по адресу 2000 - адресу, находящемуся в переменной m. Операция * может быть запомнена как «по адресу». В данном случае оператор можно прочитать как «q получает значение по адресу m».
К несчастью, значки для умножения и для взятия «по адресу» - одинаковы, впрочем как и значки битового И и «взятие адреса». Эти операторы не имеют связи друг с другом. Как & так и * имеют более высокий приоритет по сравнению с остальными арифметическими операциями, за исключением унарного минуса, имеющего такой же приоритет.
Переменные, содержащие адреса или указатели, должны объявляться путем помещения * перед именем переменной для указания компилятору того, что переменная содержит указатель. Например, для объявления указателя ch на символ, следует написать char *ch; Здесь ch - это не символ, а указатель на символ, в чем и заключается принципиальное различие. Тип данных, на который указывает указатель, как в нашем случае char, называется базовым типом указателя. Сам указатель - это переменная, используемая для хранения адреса объекта базового типа. Следовательно, указатель на символ (или любой другой указатель) имеет фиксированный размер, определяемый архитектурой компьютера, для хранения адреса. Важно запомнить, что указатель следует использовать только для указания на типы данных, совпадающие с базовым типом.
Можно смешивать объявление указателей и обычных переменных в одной строке. Например: int х, *у, count; объявляет х и count как переменные целочисленного типа, а у - как указатель на целочисленный тип.
Ниже операторы * и & используются для занесения числа 10 в переменную target: #include <stdio.h> /* присвоение с помощью * и & */ int main(void) { int target, source; int *m; source = 10; m = &source; target = *m; printf("%d", target); return 0; }