ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 31.03.2021
Просмотров: 6820
Скачиваний: 51
311
ставляются в виде массива элементов типа char. Это означает, что символы в строке будут распо-
лагаться в соседних ячейках памяти.
Необходимо отметить, что последним элементом массива является символ \0. Это «нуль-
символ», и в языке Си он используется для того, чтобы отмечать конец строки. Нуль-символ не
цифра 0; он не выводится на печать и в таблице кодов ASCII имеет номер 0. Наличие нуль-
символа означает, что количество ячеек массива должно быть. по крайней мере, на одну больше,
чем число символов, которые необходимо размещать в памяти.
Приведем пример использования строк.
Программа 84
# include<stdio.h> main()
{
char string[31] ;
scanf("%s",string) ;
printf("%s",string);
}
В этом примере описан массив из 31 ячейки памяти, в 30 из которых можно поместить один
элемент типа char. Он вводится при вызове функции scanf("%s",string); "&"отсутствует при указа-
нии массива символов.
Указатели
.
Указатель - некоторое символическое представление адреса
ячейки
памяти, от-
веденной для переменной.
Например, &name - указатель на переменную name;
Здесь & - операция получения адреса. Фактический адрес - это число, а символическое
представление адреса &name является константой типа «указатель».
В языке Си имеются и переменные типа указатель. Точно так же, как значением перемен-
ной типа char является символ, а значением переменной типа int - целое число, значением пере-
менной типа указатель служит адрес некоторой величины.
Если мы дадим указателю имя ptr, то сможем написать такой оператор:
ptr = &name;/* присваивает адрес name переменной ptr */
Мы говорим в этом случае, что prt «указатель на» name. Различие между двумя формами
записи: ptr и &name - в том, что prt - это переменная, в то время как &name - константа. В случае
необходимости можно сделать так, чтобы переменная ptr указывала на какой-нибудь другой объ-
ект:
ptr
= &bah; /* ptr указывает на bah, а не на name */
Теперь значением переменной prt является адрес переменной bah. Предположим, мы знаем,
что в переменной ptr содержится ссылка на переменную bah. Тогда для доступа к значению этой
переменной можно воспользоваться операцией «косвенной адресации» * :
val = *ptr; /* определение значения, на которое указывает ptr */ Последние два оператора,
взятые вместе, эквивалентны следующему:
val = bah;
Итак, когда за знаком
&
следует имя переменной, результатом операции является адрес
указанной переменной; &nurse дает адрес переменной nurse; когда за знаком * следует указатель
на переменную, результатом операции является величина, помещенная в ячейку памяти с указан-
ным адресом.
Пример:
nurse
=
22;
ptr = &nuse;
/*
указатель на nurse */
val = *ptr;
Результат- присваивание значения 22 переменной val.
Недостаточно сказать, что некоторая переменная является указателем. Кроме этого необхо-
димо сообщить, на переменную какого типа ссылается данный указатель. Причина заключается в
том, что переменные разных типов занимают различное число ячеек памяти, в то время как для
некоторых операций, связанных с указателями, требуется знать объем отведенной памяти.
Примеры
правильного описания указателей: int *pi; char *pc;
Спецификация типа задает тип переменной, на которую ссылается указатель, а символ *
определяет саму переменную как указатель. Описание вида int *pi; говорит, что pi - это указатель
и что *pi - величина типа int.
312
В языке Си предусмотрена возможность определения имен типов данных. Любому типу
данных с помощью определения typedef можно присвоить имя и использовать это имя в дальней-
шем при описании объектов.
Формат: typedef <старый тип> <новый тип>
Пример:
typedef long LARGE; /* определяется
тип large, эквивалентный типу long */
Имена производного типа рекомендуется записывать прописными буквами, чтобы они вы-
делялись в тексте программы.
Определение typedef не вводит каких-либо новых типов, а только добавляет новое имя для
уже существующего типа. Описанные таким способом переменные обладают точно теми же свой-
ствами, что и переменные, описанные явно. Переименование типов используется для введения ос-
мысленных или сокращенных имен типов, что повышает понятность программ, и для улучшения
переносимости программ (имена одного типа данных могут различаться на разных компьютерах).
Операции.
Язык Си отличается большим разнообразием операций (более 40). Здесь мы
рассмотрим лишь основные из них, табл. 3.3.
Арифметические операции
.
К ним относят
• сложение(+),
• вычитание (бинарное) (-),
• умножение (*),
• деление (/),
• остаток от деления нацело (%),
• вычитание (унарное) (-) .
В языке Си принято правило: если делимое и делитель имеют тип int, то деление произво-
дится нацело, т е. дробная часть результата отбрасывается.
Как обычно, в выражениях операции умножения, деления и нахождения остатка выполня-
ются раньше сложения и вычитания. Для изменения порядка действий используют скобки.
Программа 85
#include<stdio.h>
main()
(
int s;
5 = -3 + 4 * 5 - 6; printf("%d\n",s);
s = -3 + 4%5 - 6; printf("%d\n",s);
s = -3 * 4% - 6/5; printf("%d\n",s);
s= (7 + 6)%5/2; printf("%d\n",s);
}
Результат выполнения программы: 11
1
0
1
Таблица 3.3 Старшинство и порядок выполнения операций
Приоритет
Операция
Название
Порядок выполнения
Высший
()
[]
++
--
(тип)
*
Круглые скобки
Квадратные скобки Уве-
личение
Уменьшение
Приведение
Содержимое
Слева направо
Слева направо
Справа налево
Справа налево
Справа налево
Справа налево
1
&
-
!
/
~
sizeof
*
Адрес
Унарный минус Логиче-
ское «НЕ»
Инверсия битов
Размер объекта Умноже-
ние
Справа налево
Справа налево
Справа налево
Справа налево
Справа налево
Слева направо
2
\
%
Деление
Остаток
Слева направо
Слева направо
313
3
+
-
Сложение
Вычитание
Слева направо
Слева направо
4
»
«
>
Сдвиг вправо
Сдвиг влево
Больше
Слева направо
Слева направо
Слева направо
5
>=
<
<=
Больше или равно
Меньше
Меньше или равно
Слева направо
Слева направо
Слева направо
6
= =
!=
Равно
Не равно
Слева направо
Слева направо
7
&
Битовое «И»
Слева направо
8
~
Битовое
исключающее
«ИЛИ»
Слева направо
9
|
Битовое «ИЛИ»
Слева направо
10
&&
Логическое «И»
Слева направо
11
||
=
+=
Логическое «ИЛИ»
Операция присвания
Справа налево
Слева направо
Справа налево
12
- =
*=
/=
%=
Специальная форма опе-
рации присваивания
Справа налево
Справа налево
Справа налево
Справа налево
В программировании часто встречаются ситуации, когда надо увеличить или уменьшить
значение некоторой переменной на 1. Для этого обычно выполняются оператор присваивания ви-
да: s= s + 1;
В языке Си для этих действий существуют специальные операции:
• увеличение (+
+),
• уменьшение (--).
Следующие записи на языке Си являются эквивалентными:
i=i+l и i++; j=j-1 и j--;.
Символы "++" или "- -" записывается после имени переменной или перед ним.
Пример:
s
+ +; /* s
увеличить на единицу
*/ t - -; /* t
уменьшить на единицу
*/ + + а; /* а
увеличить на единицу
*/ --b; /* b
уменьшить на единицу */
Как и обычные присваивания, увеличение и уменьшение можно использовать в выражени-
ях. При этом существенно, с какой стороны от имени стоит знак "+ +"или "- -". Если знак стоит
перед переменной (в этом случае говорят о префиксной форме операции), то сначала выполняется
увеличение (уменьшение) значения переменной, а лишь затем полученный результат используется
в выражении. Если же знак стоит после переменной (постфиксная форма операции), то в выраже-
нии используется старое значение переменной, которое затем изменяется.
Пример:
inti,j,s;
i = j = 2; /* i и j получают значение 2 */
s = (i++) + (++J);
После выполнения этих действий переменные имеют такие значения:
314
i=3;j=3;s=5.
Операции увеличения ++ и уменьшения - - можно применять топько к переменным, выра-
жения типа s=(i+j)++ являются незаконными. Кроме того, не рекомендуется:
1) применять операции увеличения или уменьшения к переменной, присутствующей в бо-
лее чем одном аргументе функции,
2) применять операции увеличения
или уменьшения к переменной, которая входит в выра-
жение более одного раза.
Операции отношения и логические операции
Больше или равно
>=
Больше
>
Меньше или равно
<=
Меньше
<
Равно
==
Неравно
!=
Логическое «и»
&&
Логическое «или»
||
Отрицание «не»
!
Логическое значение «ложь» представляется целым нулевым значением, а значение «исти-
на» представляется любым ненулевым значением
Выражения, связанные логическими операциями && и ||, вычисляются слева направо, при-
чем вычисление значения выражения прекращается сразу же, как только становится ясно, будет ли
результат истинен или ложен.
Старшинство операции && выше, чем у операции ||.
Программа 86
#include<stdio.h>
main()
(
int x, у, z;
x=l; y=l; z=0; x=x&&y||z; printf("%d\n",x);
x=x|| !y&&z; printf("%d\n",x) ;
x=y=l; z=x++-l; printf("%d\n",x);printf("%d\n",z) ;
z+=-x++ + ++y; printf("%d\n",x) ; printf("%d\n",z);
z=x/++x; printf("%d\n",x); printf("%d\n",z) ;
}
Результат выполнения программы: 1
1
2
0
3
0
4
1
Битовые операции
Битовое «и»
Битовое «или»
Битовое исключающее «или»
Сдвиг влево
Сдвиг вправо
Инверсия битов (унарная операция)
&
|
~
«
»
\ ~
Программа 87
#include<stdio.h>
main()
(
int у, х, z, k;
x=03; y=02; z=01; k=x|y&z; printf("%d\n",k) ;
315
k=x|y&~z; printf("%d\n",k) ;
k=x^y&~z; printf("%d\n",k) ;
k=x&y&&z; printf("%d\n",k) ;
x=l; y=-l;
k=!x|x; printf("%d\n",k) ;
k=-x|x; printf("%d\n",k) ;
k=x^x; printf("%d\n",k) ;
x<<=3; printf("%d\n",x);
y<<=3; printf("%d\n",y);
y>>=3; printf("%d\n",y);
}
После выполнения программы получаем следующие результаты:
3
3
1
1
1
-1
0
8
-8
8
1
9
1
Выражения
. Конструкции, включающие константы (литералы), переменные, знаки опера-
ции, скобки для управления порядком выполнения операций, обращения к функциям, называют
выражениями.
Если в выражениях встречаются операнды различных типов,
то они преобразуются к об-
щему типу в соответствии с определенными правилами:
• переменные типа char интерпретируются как целые без знака (unsigned);
• переменные типа short автоматически преобразуются в int; если один
из операндов имеет
тип unsigned, то другой (другие) также преобразуется к типу unsigned и результат имеет тип un-
signed;
• если один из операндов имеет тип int, то другой (другие) также преобразуется к
типу int и
результат имеет тип int;
• если один из операндов имеет тип char, то другой (другие) также преобразуется к типу
char и результат имеет тип char;
• во время операции присваивания значение правой части преобразуется к типу левой час-
ти, который и становится типом результата;
• в процессе преобразования int в char лишние старшие 8 бит просто отбрасываются. Кроме
того, существует возможность точно указывать требуемый тип данных, к которому необходимо
привести некоторую величину (в скобках перед этой величиной). Скобки и имя типа вместе обра-
зуют операцию, называемую
приведением типов.
Например: z=(int)x+(int)y;
6.4. ОПЕРАТОРЫ. УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ ЯЗЫКА
Операторы служат основными строительными блоками программы. В языке Си указанием
на наличие оператора служит символ «точка с запятой», стоящий в конце него.
Операторы состоят из выражений. Выражение представляет собой объединение операций и
операндов. Операндом называется то, над чем выполняется операция.
Оператор присваивания
Общий вид оператора присваивания <Имя> = <Выражение>;
Пример:
int x, у, а;
х=5;
у=х*2+7;
а=у/4;
Переменные получают значения: х=5, у=17, а=4.
В языке Си разрешается включать присваивания в выражения, т. е. присваивание
может
рассматриваться как операция с учетом старшинства и влияния скобок.
Пример:
а=(у=(х=5)*2+7)/4.
В результате переменная х получает значение 5, причем это значение участвует в дальней-
ших вычислениях. Затем выполняется умножение (5*2), сложение (10+7) и еще одно присваивание
(у=17). Переменная у получает значение 17, после чего производится деление (17/4), результат ко-
торого присваивается переменной а.
В языке Си для компактной записи операторов присваивания имеются специальные опера-
ции
+=_=*= /= %= Так, следующие две записи на языке Си эквивалентны: i = i+2 и i+=2.