Операция последовательного вычисления

Операция последовательного вычисления обозначается запятой (,) и используется для вычисления двух и более выражений там, где по синтаксису допустимо только одно выражение. Эта операция вычисляет два операнда слева направо. При выполнении операции последовательного вычисления, преобразование типов не производится. Операнды могут быть любых типов. Результат операции имеет значения и тип второго операнда. Отметим, что запятая может использоваться также как символ разделитель, поэтому необходимо по контексту различать, запятую, используемую в качестве разделителя или знака операции.

Условная операция

операнд-1 ? операнд-2 : операнд-3

Операнд-1 должен быть целого или плавающего типа или быть указателем. Он оценивается с точки зрения его эквивалентности 0. Если операнд-1 не равен 0, то вычисляется операнд-2 и его значение является результатом операции. Если операнд-1 равен 0, то вычисляется операнд-3 и его значение является результатом операции. Следует отметить, что вычисляется либо операнд-2, либо операнд-3, но не оба. Тип результата зависит от типов операнда-2 и операнда-3, следующим образом.

Пример:

max = (d<=b) ? b : d;

Переменной max присваивается максимальное значение переменных d и b.

Адресные операции

& Операция получения адреса операнда.* Операция обращения по адресу или операция косвенного обращения.

px=&x; px присваивается адрес переменной

y=*px; извлекает значение из адреса записанного в px

Операция sizeof.

SIZEOF(OBJECT)

выдает целое, равное размеру указанного объекта. (Размер определяется

в неспецифицированных единицах, называемых “байтами”, которые имеют

тот же размер, что и переменные типа CHAR). Объект может быть

фактической переменной, массивом и структурой, или именем основного

типа, как INT или DOUBLE, или именем производного типа, как структура.

8. Простое и составное присваивание в языке С. Приоритеты операций и порядок вычислений. Побочные эффекты. Операции преобразования типов.

Простое и составное присваивание в языке С

+ - * / % << >> & \^ \!

Если е1 и е2 - выражения, то

е1 оп= е2

эквивалентно

е1 = (е1) оп (е2)

Приоритет Знак операции Типы операции Порядок выполнения
() [] . -> Выражение Слева направо
- ~ ! * & ++ -- sizeof приведение типов Унарные Справа налево
* / % Мультипликативные Слева направо
+ - Аддитивные
<< >> Сдвиг
< > <= >= Отношение
== != Отношение (равенство)
& Поразрядное И
^ Поразрядное исключающее ИЛИ
| Поразрядное ИЛИ
&& Логическое И
|| Логическое ИЛИ
? : Условная
= *= /= %= += -= &= |= >>= <<= ^= Простое и составное присваивания Справа налево
, Последовательное вычисление Слева направо  

Побочные эффекты

Операции присваивания в сложных выражениях могут вызывать побочные эффекты, так как они изменяют значение переменной. Побочный эффект может возникать и при вызове функции, если он содержит прямое или косвенное присваивание (через указатель). Это связано с тем, что аргументы функции могут вычисляться в любом порядке. Например, побочный эффект имеет место в следующем вызове функции:

prog (a,a=k*2);

В зависимости от того, какой аргумент вычисляется первым, в функцию могут быть переданы различные значения.

Порядок вычисления операндов некоторых операций зависит от реализации и поэтому могут возникать разные побочные эффекты, если в одном из операндов используется операции увеличения или уменьшения, а также другие операции присваивания.

Например, выражение i*j+(j++)+(--i) может принимать различные значения при обработке разными компиляторами. Чтобы избежать недоразумений при выполнении побочных эффектов необходимо придерживаться следующих правил.

1. Не использовать операции присваивания переменной в вызове функции, если эта переменная участвует в формировании других аргументов функции.

2. Не использовать операции присваивания переменной в выражении, если эта переменная используется в выражении более одного раза.

9.Указатели и массивы в языке С. Одномерные массивы. Динамическое и статическое размещение массивов.

Указатели

Указатель - это адрес памяти, распределяемой для размещения идентификатора (в качестве идентификатора может выступать имя переменной, массива, структуры, строкового литерала). В том случае, если переменная объявлена как указатель, то она содержит адрес памяти, по которому может находится скалярная величина любого типа. При объявлении переменной типа указатель, необходимо определить тип объекта данных, адрес которых будет содержать переменная, и имя указателя с предшествующей звездочкой (или группой звездочек). Формат объявления указателя:

спецификатор-типа [ модификатор ] * описатель.

Спецификатор-типа задает тип объекта и может быть любого основного типа, типа структуры, смеси (об этом будет сказано ниже). Задавая вместо спецификатора-типа ключевое слово void, можно своеобразным образом отсрочить спецификацию типа, на который ссылается указатель. Переменная, объявляемая как указатель на тип void, может быть использована для ссылки на объект любого типа. Однако для того, чтобы можно было выполнить арифметические и логические операции над указателями или над объектами, на которые они указывают, необходимо при выполнении каждой операции явно определить тип объектов. Такие определения типов может быть выполнено с помощью операции приведения типов.

В качестве модификаторов при объявлении указателя могут выступать ключевые слова const, near, far, huge. Ключевое слово const указывает, что указатель не может быть изменен в программе. Размер переменной объявленной как указатель, зависит от архитектуры компьютера и от используемой модели памяти, для которой будет компилироваться программа. Указатели на различные типы данных не обязательно должны иметь одинаковую длину.

Для модификации размера указателя можно использовать ключевые слова near, far, huge.

Примеры:

unsigned int * a;/*переменная а представляет собой указатель

на тип unsigned int (целые числа без знака) */

double * x; /*переменная х указывает на тип данных с

плавающей точкой удвоенной точности */

char * fuffer ; /* объявляется указатель с именем fuffer

который указывает на переменную типа char */

double nomer;

void *addres;

addres = & nomer;

(double *)addres ++;

/* Переменная addres объявлена как указатель на объект любого типа.

Поэтому ей можно присвоить адрес любого объекта (& - операция вычисления

адреса). Однако, как было отмечено выше, ни одна арифмитическая операция

не может быть выполнена над указателем, пока не будет явно определен тип

данных, на которые он указывает. Это можно сделать, используя операцию

приведения типа (double *) для преобразования addres к указателю на тип

double, а затем увеличение адреса. */

const * dr;

/* Переменная dr объявлена как указатель на константное выражение,

т.е. значение указателя может изменяться в процессе выполнения программы,

а величина, на которую он указывает, нет. */

unsigned char * const w = &obj.

/* Переменная w объявлена как константный указатель на данные типа

char unsigned. Это означает, что на протяжение всей программы

w будет указывать на одну и ту же область памяти. Содержание же

этой области может быть изменено. */

Массивы

Массивы - это группа элементов одинакового типа (double, float, int и т.п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве. Объявление массива имеет два формата:

спецификатор-типа описатель [константное - выражение];

спецификатор-типа описатель [ ];

Описатель - это идентификатор массива.

Спецификатор-типа задает тип элементов объявляемого массива. Элементами массива не могут быть функции и элементы типа void.

double b[10]; /* вектор из 10 элементов имеющих тип double */

Наши рекомендации