Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Сабуров С.В. - Язык программирования C и C++ - 2006

.pdf
Скачиваний:
312
Добавлен:
13.08.2013
Размер:
1.42 Mб
Скачать

Язык программирования Си

присваиваниях, cast операциях, вызовах функций и при выполнении операций.

Операнды

Операнд в Си — это константа, идентификатор, строка, вызов функции, индексное выражение, выражение выбора структурного элемента или более сложное выражение, сформированное комбинацией операндов и операций или заключением операндов в скобки. Любой операнд, который имеет константное значение, называется константным выражением.

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

Константы

Операнду константе соответствует значение и тип представляющей его константы. Константа символ имеет тип int. Целая константа имеет типы: int, long, unsigned int или unsigned long, в зависимости от размера целого и от того как специфицирована его величина. Константы с плавающей точкой всегда имеют тип double.

Идентификаторы

Идентификаторы именуют переменные и функции. Каждый идентификатор имеет тип, который устанавливается при его объявлении. Значение идентификатора зависит от типа следующим образом:

идентификаторы целых и плавающих типов представляют величины соответствующего типа.

идентификатор перечисляющего типа представляет значение одной константы из множества значений констант в перечислении. Значение идентификатора равно значению этой константы. Тип значения есть int, что следует из определения перечисления.

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

57

Язык программирования Си

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

идентификатор, объявленный как массив, представляет указатель, чье значение является адресом первого элемента массива. Тип адресуемых указателем величин — это тип элементов массива. Например, если series объявлен как массив целых из 10 ти элементов, то идентификатор series представляет адрес массива, тогда как индексное выражение series[5] ссылается на шестой элемент массива. Адрес массива не изменяется во время выполнения программы, хотя значения отдельных элементов могут изменяться. Значение указателя, представленное идентификатором массива, не является переменной и поэтому идентификатор массива не может появляться в левой части операции присваивания.

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

Тип, адресуемый указателем, — это специфицированный тип функционального возврата. Адрес функции не изменяется во время выполнения программы. Меняется только значение возврата. Таким образом, идентификаторы функции не могут появляться в левой части операции присваивания.

Строки

Строковый литерал состоит из последовательности символов, заключенных в двойные кавычки. Строковый литерал представляется в памяти как массив элементов типа char. Строковый литерал представляет адрес первого элемента этого массива. Адрес первого элемента строки является константой, так же как и сама строка.

Так как строковые литералы — это полноценные указатели, то они могут быть использованы в контексте, допускающем величины типа указателей, подчиняясь при этом тем же самым ограничениям. Строковые литералы имеют все же одно дополнительное ограничение: они не изменяемы и не могут появиться в левой части операции присваивания.

58

Язык программирования Си

Последним символом строки всегда является символ нуль 0.

Символ нуль не видим в строковом выражении, но он добавляется как последний элемент, когда строка запоминается. Таким образом, строка abc содержит четыре символа, а не три.

Вызовы функций

Синтаксис:

<expression>(<expression lils>)

Вызов функции состоит из выражения <expression>, за которым следует список выражений <expression list>. Значению выражения соответствует адрес функции (например, значение идентификатора функции). Значение каждого выражения из списка выражений (выражения в списке разделены запятыми) соответствует фактическому аргументу функции. Список выражений может быть пустым.

Выражение вызова функции имеет значение и тип своего возврата. Если тип возврата функции void, то и выражение вызова функции имеет тип void. Если возврат из вызванной функции произошел не в результате выполнения оператора return, то значение функции не определено.

Индексные выражения

Синтаксис:

<expression1>[<expression2>]

Здесь квадратные скобки — это терминальные символы. Индексное выражение представляет величину, адрес которой состоит из суммы значений выражения1 <expression1> и выражения2 — <expression2>. Выражение1 — это любой указатель, такой как идентификатор массива, а выражение2 — это целочисленная величина. Выражение2 должно быть заключено в квадратные скобки [].

Индексное выражение обычно используется для ссылок на элементы массива, тем не менее, индекс может появиться с любым указателем.

Индексное выражение вычисляется путем сложения целой величины <expression2> с значением указателя <expression1> c последующим применением к результату операции разадресации *. Например, для одномерного массива следующие четыре

59

Язык программирования Си

выражения эквивалентны в предположении, что a — это указатель, а b — это целое.

a[b]

*(a + b)

*(b + a) b[a]

В соответствии с правилами преобразования типов для операции сложения, целочисленная величина преобразуется к адресному представлению путем умножения ее на размер типа, адресуемого указателем. Например, предположим, что идентификатор line ссылается на массив величин типа int. Чтобы вычислить выражение line[i], целая величина i умножается на размер типа int. Преобразованное значение i представляет i позиций типа int. Это преобразованное значение складывается с начальным значением указателя line, что дает адрес, который расположен на i позиций типа int от line.

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

Заметим, что индексное выражение line[0] представляет значение первого элемента массива, так как отсчет смещения ведется от нуля.

Следовательно, такое выражение, как line[5], ссылается на шестой элемент массива.

Ссылки на многомерный массив

Индексное выражение может быть снова проиндексировано. Синтаксис такого выражения следующий:

<expression1>[<expression2>][<expression3>]...

Данное индексное выражение интерпретируется слева направо. Сначала вычисляется самое левое индексное выражение

<expression1>[<expression2>]. Адрес результата сложения

<expressin1> и <expression2> имеет смысл адресного выражения, с которым складывается <expression3> и т.д. Операция разадресации осуществляется после вычисления последнего индексного выражения. Однако, операции разадресации не производится, если значение последнего указателя адресует величину типа массив.

60

Язык программирования Си

Выражения с несколькими индексами ссылаются на элементы многомерных массивов. Многомерный массив — это массив, элементами которого являются массивы. Например, первым элементом трехмерного массива является массив с двумя измерениями.

Выражения с операциями

Выражения с операциями могут быть унарными, бинарными или тернарными. Унарное выражение состоит из операнда с предшествующей унарной операцией <unop> или операнда, заключенного в круглые скобки, с предшествующим ему ключевым словом sizeof.

Синтаксис:

<unop><operand>

sizeof<operand>

Бинарное выражение состоит из двух операндов, разделенных бинарной операцией <binop>.

Синтаксис:

<operand><binop><operand>

Тернарное выражение состоит из трех операндов, разделенных тернарной операцией ?:

Синтаксис:

<operand> ? <operand> : <operand>

Выражения присваивания используют унарные, бинарные и составные операции присваивания. Унарными операциями присваивания являются инкремент ++ и декремент . Бинарная операция присваивания всего одна =. Составные операции присваивания будем обозначать как <compound assign ops>. Каждая составная операция присваивания — это комбинация бинарной операции с простой операцией присваивания.

Синтаксис выражений присваивания:

<operand> ++ <operand> ++ <operand><operand>

<operand> = <operand>

<operand> <compound assignment ops> <operand>

61

Язык программирования Си

Выражения в скобках

Любой операнд может быть заключен в скобки. Они не влияют на тип и значение выражения, заключенного в скобки. Например, в выражении (10 + 5) / 5 скобки, заключающие запись 10 + 5, означают, что величина 10 + 5 является левым операндом операции деления. Результат выражения (10 + 5) / 5 равен 3. Без скобок значение записи 10 + 5 / 5 равнялось бы 11. Хотя скобки влияют на то, каким путем группируются операнды в выражении, они не гарантируют детальный порядок вычисления выражения.

Type!cast выражения

Type cast выражения имеют следующий синтаксис:

(<type name>)<operand>

Константные выражения

Константное выражение — это выражение, результатом вычисления которого является константа. Операндами константного выражения могут быть целые константы, константы символы, плавающие константы, константы перечисления, type cast выражения целого и плавающего типов и другие константные выражения. Операнды могут комбинироваться и модифицироваться посредством операций.

Константные выражения не могут использовать операции присваивания или бинарную операцию последовательного вычисления. Унарная операция адресации & может быть использована только при некоторых инициализациях.

Константные выражения, используемые в директивах препроцессора, имеют дополнительные ограничения, поэтому называются ограниченнымиконстантными выражениями:

<restricted constant expression>

Ограниченные константные выражения не могут содержать sizeof выражений, констант перечисления или type cast выражений любого типа. Они могут, однако, содержать специальные константные, имеющие синтаксис:

defined(<identifier>)

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

62

Язык программирования Си

переменной внешнего уровня с основными и структурными типами, а также с типом совмещения и массивом внешнего уровня, индексированным константным выражением.

В этих выражениях допускается сложение или вычитание с адресными подвыражениями.

Операции

Си операции требуют один операнд (унарные операции), два операнда (бинарные операции) или три операнда (тернарная операция). Операции присваивания — это унарные или бинарные операции.

Унарными операциями Си являются следующие:

! ~ !

Операции дополнения.

* &

Операции разадресации и адресации.

sizeof

size операция.

Интерпретация унарных операций производится справа налево. Бинарные операции интерпретируются слева направо. Бинарными операциями являются следующие:

* / %

Мультипликативные операции.

+ !

Аддитивные операции.

<< >>

Операции сдвига.

< > <= >= == !=

Операции отношений.

& | ^

Операции с битами.

,

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

63

Язык программирования Си

&& |

Логические операции.

В Си имеется одна тернарная операция — это операция условия ?:. Она интерпретируется справа налево.

Обычные арифметические преобразования

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

Арифметические преобразования, приведенные ниже, называются обычные арифметические преобразования.

Обычные арифметические преобразования осуществляются следующим образом:

1.Операнды типа float преобразуются к типу double.

2.Если один операнд типа double, то второй операнд преобразуется к типу double.

3.Любые операнды типов char или short преобразуются к int.

4.Любые операнды типов unsigned char или unsigned short

преобразуются к типу unsigned int.

5.Если один операнд типа unsigned long, то второй операнд преобразуется к типу unsigned long.

6.Если один операнд типа long, то второй операнд преобразуется к типу long.

7.Если один операнд типа unsigned int, то второй операнд преобразуется к unsigned int.

Операции дополнения

Арифметическое отрицание

Операция арифметического отрицания вырабатывает отрицание своего операнда. Операнд должен быть целой или

64

Язык программирования Си

плавающей величиной. При выполнении операции осуществляются обычные арифметические преобразования.

Двоичное дополнение (~)

Операция двоичного дополнения вырабатывает двоичное дополнение своего операнда. Операнд должен быть целого типа. Обычные арифметические преобразования осуществляются. Результат имеет тип преобразованного операнда.

Логическое не (!)

Операция логического не (!) вырабатывает значение 0, если операнд есть true и значение 1, если операнд есть false. Результат имеет тип int. Операнд должен быть целого, плавающего или адресного типа.

Операция адресации и разадресации

Разадресация (*)

Разадресуемая величина доступна операции разадресации через указатель. Операнд должен быть указателем величины. Результатом операции является величина, на которую указывает операнд. Типом результата является тип, адресуемый указателем. Если значение указателя равно нулю, то результат непредсказуем.

Адресация (&)

Операция адресации (&) вырабатывает адрес своего операнда. Операндом может быть любая величина, которая допустима в качестве любого операнда операции присваивания.

Результат операции адресации является указателем на операнд. Тип, адресуемый указателем, является типом операнда.

Операция адресации не может применяться к битовым полям памяти структур, она не может быть применена также к идентификаторам класса памяти register.

Операция sizeof

Операция sizeof определяет размер памяти, который соответствует идентификатору или типу. Выражение sizeof имеет форму:

sizeof(<name>)

где <name> — или идентификатор или имя типа. Имя типа не может быть void. Значением выражения sizeof является размер

65

Язык программирования Си

памяти в байтах, соответствующий поименованному идентификатору или типу.

Когда операция sizeof применяется к идентификатору массива, то результатом является размер всего массива в байтах, а не размер указателя, соответствующего идентификатору массива.

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

buffer = calloc(100, sizeof(int));

Используя sizeof операцию, можно избежать машинной зависимости, специфицируя в программе машинно зависимые размеры данных. В примере используется операция sizeof, чтобы передать размер int, зависящий от машины, как аргумент функции, поименованной calloc. Значение, возвращаемое функцией, запоминается в буфер.

Мультипликативные операции

Мультипликативные операции выполняют операции умножения *, деления / и получения остатка от деления %. Операндами операции % должны быть целые числа. Операции умножения * и деления / выполняются над целыми и плавающими операндами. Типы первого и второго операндов могут отличаться.

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

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

66

Соседние файлы в предмете Программирование на C++