Использование этой группы операторов дает возможность обращения к отдельным битам двоичного представления целочисленных операндов. В С существует 5 бинарных и один унарный побитовый оператор.
& - побитовое И; | - побитовое ИЛИ;
^ - побитовое исключающее ИЛИ; <<, >> - побитовые сдвиги; ~ - побитовое отрицание.
Оператор & выполняет побитовую конъюнкцию своих операндов. a=2;
b=6;
c=a&b;
Оператор | выполнят побитовую дизъюнкцию своих операндов. Его можно, в частности, использовать для проверки числа на четность:
if((a|1)==a)
Оператор ^ устанавливает 1 в том разряде результата, в котором соответствующие разряды операндов имеют различное значение, и О, если в этих разрядах значения совпадают.
a=2;
b=6;
c=a^b;
Операторы << и >> выполняют сдвиг в соответствующем направлении своего левого операнда на число позиций, задаваемое правым операндом, который должен быть положительным. При сдвиге беззнаковых величин освобождающиеся биты заполняются нулями, а при сдвиге вправо знаковой величины результат зависит от реализации.
a=2; d=a--; d=d<<a;
Унарный оператор ~ превращает единичные биты в нулевые и наоборот.
Операторы присваивания.
В выражениях типа a=a+t;, в которых стоящая в левой части присваивания переменная, повторяется и справа, может использоваться видоизмененная форма оператора присваивания: a+=t;.
Таким образом, в С имеется одиннадцать операторов присваивания: =,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=.
Программирование на языке высокого уровня 09.03.01 |
16 |
Ввыражениях с использованием видоизмененной формы
оператора |
присваивания |
вторым |
операндом |
является |
все, |
находящееся справа от оператора присваивания: |
|
|
|||
a*=b+1; равносильно a=a*(b+1); |
|
|
|
||
|
Условное выражение. |
|
|
||
Если |
в программе возникает необходимость |
реализовать |
выбор |
||
в пределах выражения, и в пределах этого же выражения воспользоваться результатом этого выбора, то можно воспользоваться тернарным оператором ?:. Его синтаксис:
операнд 1 ? операнд 2 : операнд 3 Первым вычисляется операнд 1, который расценивается как
условие. Если результатом вычисления операнда 1 оказалась истина, то вычисляется выражение, являющееся операндом 2, и результат вычисления этого выражения оказывается результатом всего тернарного оператора. В противном случае вычисляется выражение, являющееся операндом 3, и снова его значение является значением всего условного выражения.
a=4;
b=3; c=(a==b?b++:--a);
Условное выражение обычно берется в скобки, так как этот оператор имеет достаточно низкий приоритет (хотя он выше приоритета оператора присваивания)
for(i=1;i<=n;i++)
for(j=1;j<=m;j++) printf(“%d%c”,a[i][j],j!=m?’ ‘:’\n’);
Преобразование типов.
Вслучае, если в одной бинарной операции участвуют операнды разных типов, еще до выполнения операции тип операнда, занимающего меньше места в памяти, приводится к типу другого операнда. Такое неявное приведение типа является временным, только в пределах проводимой операции. Результат будет иметь “старший” тип.
Воперациях присваивания правила другие: значение правой части приводится к типу левой части, который и является типом результата.
Кроме неявного преобразования типов существует и унарный оператор явного преобразования, который называется оператором приведения типа. Его синтаксис:
(тип)выражение; a=(float)sum/n;
Программирование на языке высокого уровня 09.03.01 |
17 |
Оператор приведения на самом деле не меняет тип переменной, а временно генерирует значение нового типа.
Таблица приоритетов.
В таблице приоритетов операторы, перечисленные на одной строке, имеют одинаковый приоритет, строки упорядочены по убыванию приоритетов.
Операторы |
Выполняются |
|
|
() [] -> . |
слева направо |
|
|
! ~ ++ -- + - * & (тип) sizeof |
справа налево |
|
|
* / % |
слева направо |
|
|
+ - |
слева направо |
|
|
<< >> |
слева направо |
|
|
< <= > >= |
слева направо |
|
|
== != |
слева направо |
|
|
& |
слева направо |
|
|
^ |
слева направо |
|
|
| |
слева направо |
|
|
&& |
слева направо |
|
|
|| |
слева направо |
|
|
?: |
справа налево |
|
|
= += -= *= /= %= &= ^= |= <<= >>= |
справа налево |
|
|
, |
слева направо |
|
|
Темы 17-20. Массивы и указатели. Обработка текстов и файлов.
Основные свойства массивов.
Массив – это набор данных, элементы которого образуют упорядоченную последовательность, причем все эти элементы должны быть одного типа.
Как и обычные переменные, массивы в С описываются в начале функции или в начале блока, причем при описании массива, как правило, указывается количество ячеек, под которое будет выделяться память.
тип имя[константа 1][константа 2]..[константа n]
Количество размерностей массива стандартом не ограничивается. Если константное выражение в квадратных скобках присутствует, то оно должно быть натуральным числом. Если константное выражение отсутствует, то считается, что описание не завершено. Завершить описание можно двумя способами: либо при другом описании, либо при инициализации массива.
int a[]={5,6,7,8}.
Программирование на языке высокого уровня 09.03.01 |
18 |
Память при таком описании выделяется по числу инициализаторов. Счет элементов в массивах начинается с 0. Инициализаторы могут присутствовать и при явно заданном размере массива. Если число инициализаторов меньше размерности массива, то оставшиеся элементы получают значение 0. Если число инициализаторов больше размерности, то выдается сообщение о синтаксической ошибке.
int a[50]={0}; - обнуление массива.
Вмногомерных массивах пустой может быть только первая размерность.
int a[3][3]={3,4,5,6};-массив заполняется по строкам int a[3][3]={{3,4},{5},{6}};
Вмногомерных массивах хранение организовано так, что самый правый индекс в паре или наборе индексов меняется чаще всего.
Хотя память под массив выделяется непрерывным куском, особенности статического распределения памяти приводят к тому, что элементы могут и не храниться связным участком.
Символьные массивы можно инициализировать и без использования фигурных скобок:
char mas[]=”Скоро зачет\n”;
Память будет выделена с учетом символа “\0”. При помощи функции printf символьный массив можно распечатать не используя операторы цикла:
printf(“%s”,mas);
Понятие об указателях.
Указатель – это некоторая переменная, значение которой является адресом другой переменной.
Указатели описываются специальным образом: тип *имя;
float *t; - t будет хранить адреса переменных типа float. Адрес сам по себе является целым числом, память под
указатель выделяется как под целое, но для нормальной работы с указателем необходимо знать тип переменной, адрес которой хранит указатель.
Для извлечения адресов служит унарная операция &, которая называется операцией получения адреса.
t=&b; - t хранит адрес b или указывает на b.
Унарная операция * позволяет извлечь содержимое ячейки, на которую указывает переменная, стоящая после символа *. Эта операция называется операцией доступа по указателю.
k=*t;
t=&b; k=*t; равносильно k=b;
Программирование на языке высокого уровня 09.03.01 |
19 |
Связь указателей и массивов.
Любой доступ к элементу массива, осуществляемый с помощью операции индексирования, может быть осуществлён и при помощи указателя.
int a[10]; int *x=&a[0];
х указывает на нулевой элемент массива а, или, иначе говоря, x содержит адрес элемента a[0]. В этом случае адрес любого i-ого элемента массива можно представить как x+i, а его значение – как *(x+i).
Подобные операции верны для любого типа и размера массивов, так как при прибавлении к указателю целого числа i указатель «сдвигается» не на i байтов, а на i элементов этого типа.
x=&a[0]; равносильно |
x=a; |
Если где-либо на |
протяжении программы используется |
идентификатор массива без указания индекса, то эта переменная имеет значение, равное адресу нулевого элемента массива.
Существуют и другие способы записи элементов массива и их адресов. Так a[i] можно записать как *(a+i), а запись &a[i]
эквивалентна записи a+i. С другой стороны, |
если x – указатель, |
то в выражениях его можно использовать с |
индексом, то есть |
запись x[i] эквивалентна записи *(x+i). |
|
Между указателем, которому присвоен адрес нулевого элемента массива, и именем массива существует важное различие. Указатель является переменной, поэтому его значение по ходу программы можно менять (x=a; x++;). Имя массива без указания индекса не может находить в левой части оператора присваивания (записи a++; или a=x; - недопустимы). Это связано с тем, что участок памяти, выделенный под массив, не изменяется на протяжении работы программы.
Над указателями допустимо выполнение следующих операций:
- присвоение указателю в качестве начального значения адреса объекта данных или нуля;
-прибавление к указателю или вычитание из указателя целого числа;
-сравнение двух указателей;
-вычитания одного указателя из другого, если оба указателя указывают на объекты одного типа.
Следующий фрагмент программы можно записать разными способами:
1.int a[5]={3,7,11,8,2}, i, max; max=a[0];
for(i=1;i<=4;i++)
if(a[i]>=max)
max=a[i];
Программирование на языке высокого уровня 09.03.01 |
20 |