Операнды и операции
Операнд- это константа, литеральная строка, идентификатор, вызов функции, индексное выражение, выражение выбора элемента или более сложное выражение, сформированное комбинацией операндов, знаков операций и круглых скобок. Любой операнд, который имеет константное значение, называется константным выражением. Каждый операнд имеет тип.
Если в качестве операнда используется константа, то ему соответствует значение и тип представляющей его константы. Целочисленная константа может быть типа char, int, long, unsigned int, unsigned long, в зависимости от ее значения и от формы записи. Символьная константа имеет тип char. Константа с плавающей точкой всегда имеет тип float.
Литеральная строка состоит из последовательности символов, заключенных в кавычки, и представляется в памяти как массив элементов типа char, инициализируемый указанной последовательностью символов.
Значением литеральной строки является адрес первого элемента строки и синтаксически литеральная строка является немодифицируемым указателем на тип char. Литеральные строки могут быть использованы в качестве операндов в выражениях, допускающих величины типа указателей. Но т. к. строки не являются переменными, их нельзя использовать в левой части операции присваивания.
Следует помнить, что последним символом строки всегда является '\0', который автоматически добавляется при хранении строки в памяти.
Идентификаторы переменных и функций. Каждый идентификатор имеет тип, который устанавливается при его объявлении или определении.
Значение идентификатора зависит от типа следующим образом:
- идентификаторы переменных целых и плавающих типов представляют значения соответствующего типа;
- идентификатор переменной типа enum представлен значением одной константы из множества значений констант, указанных в перечислении. Значением идентификатора является константное значение. Тип значения - int, что следует из определения перечисления;
- идентификатор переменной типа struct или union представляет значение, определенное структурой или объединением;
- идентификатор, объявляемый как указатель, представляет указатель на значение, заданное в объявлении типа;
- идентификатор, объявляемый как массив, представляет указатель, значение которого является адресом первого элемента массива. Тип адресуемых указателем величин - это тип элементов массива. Отметим, что адрес массива не может быть изменен во время выполнения программы, хотя значение отдельных элементов может изменяться.
Значение указателя, представляемое идентификатором массива, не является переменной, и поэтому идентификатор массива не может появляться в левой части оператора присваивания;
- идентификатор, объявляемый как функция, представляет указатель, значение которого является адресом функции, возвращающей значения определенного типа и могущей иметь параметры определенного типа. Адрес функции не изменяется во время выполнения программы, меняется только возвращаемое значение. Таким образом, идентификаторы функций не могут появляться в левой части операции присваивания.
Вызов функции состоит из выражения, за которым следует необязательный список выражений в круглых скобках:
Выражение1 '('[Список выражений]')'
Значением Выражения1 должен быть адрес функции (например, ее идентификатор). Значения каждого выражения из Списка выражений передаются в функцию в качестве фактического аргумента. Операнд, являющийся вызовом функции, имеет тип и значение возвращаемого функцией значения.
Индексное выражение задает элемент массива и имеет вид:
Выражение 1 '[' Выражение2 ']'
Тип индексного выражения совпадает с типом элементов массива, а значение представляет величину, адрес которой вычисляется с помощью
Значений Выражение 1 и Выражение2.
Обычно Выражение1 - это указатель, например, идентификатор массива, а Выражение2 - это целочисленная величина. Однако требуется только, чтобы одно из выражений было указателем, а второе целочисленной величиной. Поэтому Выражение1 может быть целочисленной величиной, а Выражение2 - указателем. В любом случае Выражение2 должно быть заключено в квадратные скобки. Хотя индексное выражение обычно используется для ссылок на элементы массива, тем не менее, индекс может появляться с любым указателем.
Индексные выражения используются для ссылки на элементы одномерного массива. При этом адрес этого элемента вычисляется путем сложения целой величины, указанной в качестве индекса и умноженной на размер элемента массива, с начальным адресом массива. При этом в качестве индекса может быть использована не только константа, но и выражение любой сложности, результатом которого будет целочисленная величина.
Пусть, например, объявлен массив элементов типа float.
float arr[10];
Чтобы получить доступ к 5-му элементу массива аrr, нужно написать аrr[5]. При этом индекс 5 умножается на размер переменной float-типа (четыре байта) для того, чтобы вычислить смещение 5-го элемента массива аrr относительно его начала. Затем полученное значение складывается с начальным адресом массива аrr, что в свою очередь дает адрес 5-го элемента массива.
Таким образом, результатом индексного выражения arr[i] является значение i-го элемента массива.
Многомерный массив - это массив, элементами которого являются массивы. Например, первым элементом трехмерного массива является массив с двумя измерениями. Выражение с несколькими индексами ссылается на элементы многомерных массивов.
Для ссылки на элемент многомерного массива индексное выражение должно иметь несколько индексов, заключенных в квадратные скобки:
Идентификатор массива '[' Индексное выражение1 ']' '[' Индексное выражение2 ']'…
Такое индексное выражение интерпретируется слева направо, т. е. вначале рассматривается первое индексное выражение:
Идентификатор массива '[' Индексное выражение1 ']'
Результат вычисления этого выражения - это адрес первого элемента вложенного массива, с которым складывается индексное Выражение 2, и т. д. Считывание элемента массива осуществляется после вычисления последнего индексного выражения. Отметим, что если к двумерному массиву применить только один индекс, то результатом будет не значение первого элемента вложенного массива, а его адрес.
Например, пусть объявлен трехмерный массив mass:
int mass [2] [5] [3];
Рассмотрим процесс вычисления индексного выражения mass [1] [2] [2].
1. Вычисляется выражения mass [1]. Индекс 1 умножается на размер элемента этого массива, которым является двухмерный массив, содержащий 5x3 элементов типа int. Получаемое значение складывается с начальным адресом массива mass. Результатом является адрес вложенного двухмерного массива размером (5x3) в трехмерном массиве mass.
2. Второй индекс 2 умножается на размер массива из трех элементов типа int и складывается с адресом mass [1].
3. Так как каждый элемент трехмерного массива - это величина типа int, то третий индекс 2 умножается на размер int-типа (в С-51 это два байта) перед сложением с адресом mass [1] [2].
4. Наконец, выполняется считывание значения полученного элемента массива int-типа.
Если было бы указано mass [1] [2], то результатом был бы адрес массива из трех элементов типа int. Соответственно значением индексного выражения mass [1] является адрес двухмерного массива.
Выражение выбора элемента применяется, если в качестве операнда надо использовать поле структуры или объединения. Такое выражение имеет значение и тип выбранного элемента. Рассмотрим две формы выражения выбора элемента:
Имя'.' Поле
Имя"->"Поле
В первой форме имя представляет величину типа struct или union, а поле - это имя элемента структуры или объединения. Во второй форме выражение используется при работе с указателями на структуры или объединения. При этом поле - это имя выбираемого элемента структуры или объединения. То есть выражение
Имя "->" Поле
эквивалентно записи
"(*" Имя')'.Поле
Пример:
struct tree {float num;
int spisoc[5);
struct tree *left;
} tr[5], elem;
elem.left = & elem;
В приведенном примере используется операция выбора ('.') для доступа к полю left структурной переменной elem. Таким образом, элементу left структурной переменной elem присваивается адрес самой переменной elem, т. е. переменная elem хранит указатель на себя саму.