- •Введение
- •Язык программирования Си Элементы языка программирования.
- •Множества символов
- •Буквы и цифры
- •Пробельные символы
- •Знаки пунктуации и специальные символы
- •Операции
- •Константы
- •Целые константы
- •Константы с плавающей точкой
- •Константа-символ
- •Строковые литералы
- •Идентификаторы
- •Ключевые слова
- •Комментарии
- •Лексемы
- •Структура программы
- •Исходная программа
- •Исходные файлы
- •Выполнение программ
- •Время жизни и видимость
- •Классы имен
- •Объявления
- •Спецификаторы типов
- •Область значений величин
- •Деклараторы
- •Деклараторы массивов, функций и указателей
- •Составные деклараторы
- •Объявления переменной
- •Объявление простой переменной
- •Объявление перечисления
- •Объявления структур
- •Объявление совмещений
- •Объявление массива
- •Объявление указателей
- •Объявление функций
- •Объявление классов
- •Классы памяти
- •Объявления переменной на внешнем уровне
- •Объявление переменной на внутреннем уровне
- •Объявление функции на внешнем и внутреннем уровнях
- •Инициализация
- •Базовые типы и типы указателей
- •Составные типы
- •Строковые инициализаторы
- •Объявления типов
- •Типы структур, совмещений и перечислений
- •Объявления typedef
- •Имена типов
- •Выражения и присваивания
- •Введение
- •Операнды
- •Константы
- •Идентификаторы
- •Вызовы функций
- •Индексные выражения
- •Выражение выбора структурного элемента
- •Выражения с операциями
- •Выражения в скобках
- •Type-cast выражения
- •Константные выражения
- •Операции
- •Обычные арифметические преобразования.
- •Операции дополнения
- •Операция адресации и разадресации
- •Операция sizeof
- •Мультипликативные операции
- •Аддитивные операции
- •Операции сдвига
- •Операции отношений
- •Побитовые операции
- •Логические операции
- •Операция последовательного вычисления
- •Условная операция
- •Операции присваивания
- •Lvalue-выражения
- •Унарные инкремент и декремент
- •Простое присваивание
- •Составное присваивание
- •Старшинство и порядок выполнения
- •Побочные эффекты
- •Преобразования типов
- •Преобразование типов при присваивании
- •Преобразования type-cast
- •Преобразования, выполняемые операциями
- •Преобразования при вызовах функций
- •Операторы
- •Введение
- •Оператор break
- •Составной оператор
- •Оператор continue
- •Оператор do
- •Оператор-выражение
- •Оператор for
- •Goto и помеченные операторы
- •Оператор if
- •Оператор null
- •Оператор return
- •Оператор switch
- •Оператор while
- •Функции
- •Введение
- •Определение функции
- •Класс памяти
- •Тип возврата
- •Формальные параметры
- •Тело функции
- •Объявления функции
- •Вызовы функций
- •Фактические аргументы
- •Вызовы с переменным числом аргументов
- •Рекурсивные вызовы
- •Директивы препроцессора и указания компилятору
- •Поименованные константы и макросы
- •Директива # define
- •Директива #undef
- •#Include файлы
- •Условная компиляция
- •Директивы #if, #elif, #else, #endif
- •Директивы #ifdef и #ifndef
- •Управление нумерацией строк
Lvalue-выражения
Операция присваивания означает, что значение правого операнда должно быть присвоено участку памяти, поименованному левым операндом. Поэтому левый операнд операции присваивания (или операнд унарного выражения присваивания) должен быть выражением, ссылающимся на участок памяти. Выражение, которое ссылается на участок памяти, называется Lvalue-выражением. Имя переменной является таким выражением: имя переменной указывает на участок памяти, а значением переменной является значение, находящееся в этой памяти.
Lvalue-выражениями могут быть:
Идентификаторы символьного, целого, плавающего, адресного, перечисляющего,структурного и совмещающего типов;
индексные ([]) выражения, исключая индексные выражения, вычисляющие указатель на массив или указатель на функцию;
выражение выбора структурного элемента (-> и .), если выбранный элемент является одним из вышеперечисленных выражений;
выражение унарной разадресации (*), за исключением выражений, ссылающихся на массив или функцию;
typecastдля адресных типов;
Lvalue-выражение в скобках.
Унарные инкремент и декремент
Унарная операция присваивания (++ и --) инкрементирует или декрементирует свой операнд. Операнд должен быть целого, плавающего или адресного типа. В качестве операнда допустимо также Lvalue-выражение. Операнды целого или плавающего типа преобразуются путем сложения или вычитания целой 1. Тип результата соответствует типу операнда. Операнд адресного типа инкрементируется или декрементируется размером объекта, который он адресует. Инкрементированный указатель адресует следующий объект, а декрементированный указатель - предыдущий.
Операции инкремента (++) или дектемента (--) могут появляться перед или после своего операнда. Когда операция является префиксом своего операнда, то операнд инкрементируется или дектементируется и его новое значение является результатом вычисления выражения. Когда операция является постфиксом своего операнда, то непосредственным результатом выражения является значение операнда перед его инкрементированием или декрементированием. После этого результат используется в контексте, а операнд инкрементируется или декрементируется.
Примеры
/* ... example 1 ... */
if (pos++ > 0)
*ptt = *qtt;
/* ... example 2 ... */
if (line [--i] ! = '\n')
return;
В первом примере переменная pos сравнивается с 0, а затем инкрементируется.
Во втором примере переменная i декрементируется перед ее использованием в качестве индекса line.
Простое присваивание
Операция простого присваивания (=) выполняет присваивание. Правый операнд присваивается левому операнду. При присваивании выполняются некоторые правила преобразования (смотри раздел 5.7.1).
Пример
double x;
int y;
x = y;
Значение y преобразуется к типу double и присваивается x.
Составное присваивание
Операция составного присваивания состоит из простой операции присваивания, скомбинированной с другой бинарной операцией. В составном присваивании вначале выполняется операция, специфицированная аддитивным оператором, а затем результат присваивается левому операнду. Выражение составного присваивания, например, имеет вид:
<expression 1> += <expression 2>
и может быть понято как:
<expression 1> = <expression 1> + <expression 2>
Однако, выражение составного присваивания не эквивалентно расширенной версии, поскольку в выражении составного присваивания <expression 1> вычисляется только один раз, в то время как в расширенной версии оно вычисляется дважды: в операции сложения и в операции присваивания. Каждая операция составного присваивания выполняет преобразования, которые осуществляются соответствующей бинарной операций, и соответственно ограничивает типы своих операндов. Результатом операции составного присваивания является значение и тип левого операнда.
Пример
# define MASK 0xffff
n |= MASK
В этом примере операция побитового включающего ИЛИ выполняется на n и MASK и результат присваивается n. Константа MASK явно определенная директивой препроцессора # define.