Операнды
Операндом выражения может быть константа,
идентификатор или символьная строка. Эти операнды могут посредством так называемых
первичных операций комбинироваться в первичные выражения — вызов функции,
индексное выражение, выражение выбора элемента. Эти первичные выражения, в свою
очередь, являются операндами содержащего их выражения. Комбинация их с другими
операциями приводит к образованию новых, более сложных выражений, также
являющихся операндами содержащего их выражения, и т.д. Каждый операнд имеет
тип.
Идентификаторы — это
имена переменных, однозначно определяющих соответствие переменной с ее адресом.
К идентификаторам относят: имена переменных, функций; тэги – имена типов
структур, объединений, перечислимых типов. Компилятор языка Си не допускает
использования идентификаторов, совпадающих по написанию
с ключевыми словами.
Значение объекта, именуемого идентификатором,
зависит от типа следующим образом:
1) Идентификаторы переменных целого и
плавающего типа представляют значения соответствующего типа.
2) Идентификатор переменной перечислимого
типа представляет значение одной константы из соответствующего этому типу
списка перечисления. Тип этого значения—int.
3) Идентификатор структуры или объединения
представляет совокупность значений, специфицированных этой структурой или
объединением.
4) Идентификатор указателя представляет адрес
некоторого объекта специфицированного типа. Если указателю не присвоено
никакого значения, то использование его в выражении может привести к трудно
выявляемой ошибке. В языке Си определено, что никакой программный объект не
может иметь адрес NULL (ноль), поэтому указатель со значением NULL не указывает
ни на какой объект.
5) Идентификатор массива представляет массив,
но если в выражении требуется скалярная величина, то представляет адрес первого
элемента этого массива. Тип идентификатора — указатель на тип элементов
массива. Из этого следует, что использование в выражениях массивов и указателей
имеет много общего. Во многих случаях способ организации доступа к объекту —
либо по указателю, либо как к элементу массива — не имеет принципиальной
разницы и определяется исключительно выбранным стилем программирования. Это
родство между массивами и указателями является существенной особенностью языка
Си, выделяющей его среди других языков программирования высокого уровня.
Существуют, однако, некоторые различия между
массивами и указателями. Во-первых, указатель занимает одну ячейку памяти,
предназначенную для хранения машинного адреса (в частности, адреса какого-либо
массива). Массив же занимает столько ячеек памяти, сколько элементов определено
в нем при его объявлении. Только в выражении массив представляется своим
адресом, который эквивалентен указателю. Во-вторых, адрес массива является
постоянной величиной, поэтому, в отличие от идентификатора указателя,
идентификатор массива не может составлять левую часть операции присваивания.
6) Идентификатор функции представляет
функцию, т.е. адрес точки входа в функцию. Тип идентификатора — функция,
возвращающая значение специфицированного для нее типа. Однако если в выражении
требуется скалярная величина, то типом идентификатора считается указатель на
функцию. Адрес функции не изменяется во время выполнения программы и,
следовательно, не является переменной величиной. Поэтому идентификатор функции
не может составлять левую часть операции присваивания.
Константы
Целая константа — это десятичное,
восьмеричное или шестнадцатеричное число,
которое представляет целое значение. Между
цифрами целой константы пробельные символы недопустимы. Целые
константы всегда специфицируют положительные значения. Если требуется
отрицательное значение, то необходимо сформировать константное выражение из
знака минус и следующей за ним константы. Знак минус рассматривается при этом
как арифметическая операция. Каждая целая константа имеет тип, определяющий ее представление в памяти, например, int.
Константа с плавающей точкой — это
действительное десятичное положительное число. Между цифрами или символами
константы пробельные символы недопустимы. Константы с плавающей точкой всегда
специфицируют положительные значения. -//-
Символьная константа — это
буква, цифра, знак пунктуации или специальный символ, заключенный в апострофы.
Значение символьной константы равно коду представляемого ею символа. Символьные
константы имеют тип int.
Символьные строки
Символьная строка — это
последовательность символов, заключенная в двойные кавычки. Символьная строка
рассматривается как массив символов, каждый
элемент которого представляет отдельный символ. Тип символьной строки—массив
элементов типа char. Число элементов в массиве равно числу
символов в символьной строке плюс один, поскольку нулевой символ (признак конца
символьной строки) тоже является элементом массива.
Вызовы функций
Вызов
функции.
Передает
управление и значения фактических аргументов функции. Выражение вычисляется и
его результат интерпретируется как адрес функции. Список выражений, где выражения
следуют через запятую, представляют собой перечень фактических аргументов,
передаваемых в функцию. Он может быть пустой. При выполнении вызова функции
значения фактических аргументов вычисляются, над ними выполняются необходимые
преобразования, затем они помещаются в стек, откуда эти значения извлекаются и
присваиваются формальным параметрам. Все аргументы передаются по значению и
только массивы по ссылке. Вызванная функция работает с копией фактических
аргументов и никакое изменение формальных параметров не отразится на значении
аргументов. Порядок вычисления выражений, представляющих аргументы функции не
определен в Си, что может привести к побочным эффектам. Функция может быть
вызвана не только по идентификатору. При выполнении оператора возврата return
управление передается в вызывающую функцию. Туда же передается возвращаемое
значение, если оно есть. Функция может возвращать значение любого типа, кроме
массива или функции. В частности, это может быть указатель на любой тип,
включая массив или функцию. Тип возвращаемого значения, указываемый в
определении функции, должен соответствовать типу возвращаемого значения во всех
элементах функции. Возврат значения выполняется при помощи оператора return,
содержащего выражение, которое вычисляется, преобразуется к типу возвращаемого
значения и возвращается в точку вызова функции. Если return отсутствует или не
содержит выражение, то возвращаемое значение не определено.
<идентификатор
функции> (<фактические
аргументы>)
Индексные выражения
Синтаксис:
<выражение1>[<выражение2>]
Здесь квадратные скобки являются символами
языка Си, а не элементами описания.
Значение индексного выражения находится по
адресу, который вычисляется как сумма значений <выражения1> и <выражения2>.
Одно из выражений должно быть указателем, а другое иметь целый тип. Индексное
выражение обычно используется для доступа к элементам массива, однако
индексацию можно применить к любому указателю.
Выбор элемента
Синтаксис:
<выражение>.<идентификатор>
<выражение> -> <идентификатор>
Выражение выбора элемента позволяет получить
доступ к элементу структуры или объединения. Выражение имеет значение и тип
выбранного элемента.
В первой синтаксической форме <выражение> представляет значение типа
struct или union, а идентификатор именует элемент специфицированной структуры
или объединения. Во второй синтаксической форме <выражение> представляет указатель на структуру или объединение,
а идентификатор именует элемент специфицированной структуры.
Операции и L-выражения
В зависимости от используемых операций выражения
подразделяются на первичные, унарные, бинарные, тернарные, выражения
присваивания и выражения приведения типа.
Операнды некоторых операций в языке Си должны
представлять собой так называемые L-выражения. L-выражением является выражение,
которое ссылается на ячейку памяти и потому имеет смысл в левой части бинарной
операции присваивания. Простейшим примером L-выражения является идентификатор
переменной: он ссылается на ячейку памяти, которая хранит значение этой
переменной. Поскольку L-выражение ссылается на ячейку памяти, адрес этой ячейки
может быть получен с помощью операции адресации - &.
К L-выражениям относятся:
— идентификаторы переменных целого,
плавающего, перечислимого типов, указателей, структур и объединений;
— индексные выражения, исключая те из них,
значение которых имеет тип массив;
— выражение выбора элемента, если выбранный
элемент сам является одним из допустимых L-выражений;
— выражение косвенной адресации, если только
его значение не имеет тип массив или функция;
— L-выражение в скобках;
— выражение приведения типа переменной, если
размер результирующего типа не превышает размера первоначального типа.
Скобочные выражения
Любой операнд может быть заключен в круглые
скобки. Хотя скобки влияют на то, каким путем группируются операнды в выражении,
они не гарантируют определенный порядок вычисления операндов для операций,
обладающих свойством коммутативности (мультипликативные, аддитивные,
поразрядные операции).
Константные выражения
Константное выражение — это выражение,
результатом вычисления которого является константа. Операндами константного
выражения могут быть целые, символьные, плавающие константы, константы
перечислимого типа, выражения приведения типа константного выражения, выражения
с операцией sizeof и другие
константные выражения. Имеются некоторые ограничения на использование операций
в константных выражениях. В константных выражениях нельзя использовать операции
присваивания, операцию последовательного вычисления. Кроме того, использование
операции адресации, выражений приведения типа и плавающих констант ограничено.
Константные выражения, используемые в
директивах препроцессора, имеют дополнительные ограничения, поэтому они
называются ограниченными константными выражениями. Ограниченные константные
выражения не могут содержать операцию sizeof,
констант перечисления и выражений приведения типа и плавающих констант.