Программирование СИ++

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

Рубрика Программирование, компьютеры и кибернетика
Вид учебное пособие
Язык русский
Дата добавления 17.02.2012
Размер файла 135,0 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

1

Размещено на http://www.allbest.ru/

Программирование СИ++

Учебное пособие

по дисциплине Программирование на СИ++

для студентов специальностей

Вычислительные машины, системы, комплексы и сети

Информационные системы

дневной и заочной форм обучения

г. Тольятти

2007

Учебное пособие предназначено для студентов дневной и заочной форм обучения специальностей «Вычислительные машины, системы, комплексы и сети», «Информационные системы» для изучения методов и средств программирования с помощью языка высокого уровня СИ++.

Составил: к.т.н., доц. Трубачева С.И.

Введение

Учебное пособие может быть использовано студентами специальностей «Вычислительные машины, комплексы, системы и сети», «Информационные системы» при изучении дисциплины «Программирование на СИ++.

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

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

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

Учебное пособие состоит из трех основных разделов. В первом разделе представлен материал основных конструкций языка, приемов программирования на СИ. Во втором разделе рассмотрены основные подходы объектно-ориентированного программирования: понятия, свойства, приемы программирования с использованием классов, производных классов, виртуальных функций. Третий раздел содержит примеры программ с пояснениями.

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

Раздел I. Язык программирования СИ

1.1 Переменные и операции языка СИ

1.1.1 Используемые символы

Множество символов используемых в языке СИ можно разделить на пять групп.

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

2. Группа прописных и строчных букв русского алфавита и арабские цифры.

3. Знаки нумерации и специальные символы.

Эти символы используются, с одной стороны, для организации процесса вычислений, а с другой, - для передачи компилятору определенного набора инструкций (таблица 1.1).

Таблица 1.1 - Символы языка

Знак, пояснение

Знак, пояснение

Знак, пояснение

, запятая

) круглая скобка правая

. точка

( круглая скобка левая

; точка с запятой

} фигурная скобка правая

: двоеточие

{ фигурная скобка левая

? вопросительный знак

< меньше

' апостроф

> больше

! восклицательный знак

[ квадратная скобка

| вертикальная черта

] квадратная скобка

/ дробная черта

# номер

\ обратная черта

% процент

& амперсанд

^ логическое не

+ плюс

= равно

- минус

" кавычки

* звездочка

~ тильда

4. Управляющие и разделительные символы. К той группе символов относятся: пробел, символы табуляции, перевода строки, возврата каретки, новая страница и новая строка. Эти символы отделяют друг от друга объекты, определяемые пользователем, к которым относятся константы и идентификаторы. Последовательность разделительных символов рассматривается компилятором как один символ (последовательность пробелов).

5. Кроме выделенных групп символов в языке СИ широко используются так называемые, управляющие последовательности (таблица 1.2), т.е. специальные символьные комбинации, используемые в функциях ввода и вывода информации. Управляющая последовательность строится на основе использования обратной дробной черты (\) (обязательный первый символ) и комбинацией латинских букв и цифр.

Таблица 1.2 - Управляющие последовательности

Управляющая последовательность

Наименование

Шеснадцатеричная замена

\a

Звонок

007

\b

Возврат на шаг

008

\t

Горизонтальная табуляция

009

\n

Переход на новую строку

00A

\v

Вертикальная табуляция

00B

\r

Возврат каретки

00C

\f

Перевод формата

00

D\"

Кавычки

022

\'

Апостроф

027

\0

Ноль- символ

000

\\

Обратная дробная черта

05C

\ddd

Символ набора кодов ПЭВМ в восьмеричном представлении

Например, \015 - восьмеричная управляющая последовательность

\xddd

Символ набора кодов ПЭВМ в шестнадцатеричном представлении

Например, \x00D - шестнадцатеричная управляющая последовательность

Следует отметить, что в строковых константах всегда обязательно задавать все три цифры в управляющей последовательности. Например, отдельную управляющую последовательность \n (переход на новую строку) можно представить как \010 или \xA, но в строковых константах необходимо задавать все три цифры, в противном случае символ или символы, следующие за управляющей последовательностью, будут рассматриваться как ее недостающая часть.

Кроме определения управляющей последовательности, символ обратной дробной черты (\) используется также как символ продолжения. Если за (\) следует (\n), то оба символа игнорируются, а следующая строка является продолжением предыдущей. Это свойство может быть использовано для записи длинных строк.

1.1.2 Константы

Константами называются неизменяемые переменные программы. В языке СИ разделяют четыре типа констант: целые константы, константы с плавающей запятой, символьные константы, строковыми литералы.

Целая константа: это десятичное, восьмеричное или шестнадцатеричное число, которое представляет целую величину в одной из следующих форм: десятичной, восьмеричной или шестнадцатеричной.

Десятичная константа состоит из одной или нескольких десятичных цифр, причем первая цифра не должна быть нулем (в противном случае число будет воспринято как восьмеричное). Восьмеричная константа состоит из обязательного нуля и одной или нескольких восьмеричных цифр (среди цифр должны отсутствовать восьмерка и девятка, так как эти цифры не входят в восьмеричную систему счисления). Шестнадцатеричная константа начинается с обязательной последовательности 0х или 0Х и содержит одну или несколько шестнадцатеричных цифр (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). В таблице 1.3 представлены примеры целых констант.

Таблица 1.3 - Примеры целых констант

Десятичная константа

Восьмеричная константа

Шестнадцатеричная константа

16

020

0x10

127

177

0x7F

Если требуется сформировать отрицательную целую константу, то используют знак "-" перед записью константы (который будет называться унарным минусом). Например: -0x2A, -088, -16 .

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

- десятичные константы рассматриваются как величины со знаком, им присваивается тип int (целая) или long (длинная целая) в соответствии со значением константы. Если константа меньше 32768, то ей присваивается тип int в противном случае long.

- восьмеричным и шестнадцатеричным константам присваивается тип int, unsigned int (беззнаковая целая), long или unsigned long в зависимости от значения константы.

Для того чтобы любую целую константу определить типом long, достаточно в конце константы поставить букву "l" или "L".

Примеры: 5l, 6l, 128L, 0105L, OX2A11L.

Константа с плавающей точкой - десятичное число, представленное в виде действительной величины с десятичной точкой или экспонентой.

Формат имеет вид:

[ цифры ].[ цифры ] [ Е | e [ + | - ] цифры ] .

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

Примеры: 115.75, 1.5Е-2, -0.025, .075, -0.85Е2

Символьная константа - представляется символом, заключенным в апострофы. Управляющая последовательность рассматривается как одиночный символ, допустимо ее использовать в символьных константах. Значением символьной константы является числовой код символа.

Примеры:

' '- пробел , 'Q'- буква Q , '\n' - символ новой строки , '\\' - обратная дробная черта, '\v' - вертикальная табуляция.

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

Строковая константа (литерал) - последовательность символов (включая строковые и прописные буквы русского и латинского алфавита, а также цифры, заключенные в кавычки (") . Например: "Школа № 26", “город Тольятти”.

Отметим, что все управляющие символы, кавычка ("), обратная дробная черта (\) и символ новой строки в строковом литерале и в символьной константе представляются соответствующими управляющими последовательностями. Каждая управляющая последовательность представляется как один символ. Например, при печати литерала "Школа \n № 26" его часть "Школа" будет напечатана на одной строке, а вторая часть "№ 26" на следующей строке. Символы строкового литерала сохраняются в области оперативной памяти. В конец каждого строкового литерала компилятором добавляется нулевой символ, представляемый управляющей последовательностью \0.

Строковый литерал имеет тип char[ ]. Это означает, что строка рассматривается как массив символов. Отметим важную особенность, число элементов массива равно числу символов в строке плюс 1, так как нулевой символ (символ конца строки) также является элементом массива. Все строковые литералы рассматриваются компилятором как различные объекты. Строковые литералы могут располагаться на нескольких строках. Такие литералы формируются на основе использования обратной дробной черты и клавиши ввод. Обратная черта с символом новой строки игнорируется компилятором, что приводит к тому, что следующая строка является продолжением предыдущей.

Например:

"строка неопределенной \n

длины"

полностью идентична литералу "строка неопределенной длины".

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

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

Идентификатором называется последовательность цифр и букв, а также специальных символов, при условии, что первой стоит буква или специальный символ. Для образования идентификаторов могут быть использованы строчные или прописные буквы латинского алфавита. В качестве специального символа может использоваться символ подчеркивание (_). Два идентификатора, для образования которых используются совпадающие строчные и прописные буквы, считаются различными.

Например: abc, ABC, A128B, a128b .

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

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

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

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

1.1.4 Ключевые слова

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

Приведем список ключевых слов языка: auto, double, int, struct, break, else, long, switch, register, tupedef, char, extern, return, void, case, float, unsigned, default, for, signed, union, do, if, sizeof, volatile, continue, enum, short, while

Кроме того, в версях реализации языка СИ, зарезервированными словами являются: _asm, fortran, near, far, cdecl, huge, paskal, interrupt.

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

1.1.5 Использование комментариев в тексте программы

Комментарий - это набор символов, которые игнорируются компилятором. На этот набор символов, однако, накладываются следующие ограничения. Внутри набора символов, который представляет комментарий, не может быть специальных символов, определяющих начало и конец комментариев, соответственно (/* и */). Комментарии в СИ обозначаются “//”, “/*…*/”. Отметим, что комментарии могут заменить как одну строку, так и несколько.

Например:

/* комментарии к программе */

/* начало алгоритма */

или

/* комментарии можно записать в следующем виде, однако, надо быть осторожным, чтобы внутри последовательности, которая игнорируется компилятором, не встретились операторы программы, которые также будут игнорироваться */

Неправильное определение комментариев:

/* комментарии к алгоритму /* решение краевой задачи */ */

1.2 Типы данных и их объявление

Важное отличие языка СИ от других языков является отсутствие принципа умолчания, что приводит к необходимости объявления всех переменных, используемых в программе явно вместе с указанием соответствующих им типов.

Объявления переменной имеет следующий формат:

[спецификатор-класса-памяти] спецификатор-типа

описатель [=инициатор] [,описатель [= инициатор] ]

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

Спецификатор типа - одно или несколько ключевых слов, определяющих тип объявляемой переменной. В языке СИ имеется стандартный набор типов данных, используя который можно сконструировать новые (уникальные) типы данных.

Инициатор - задает начальное значение или список начальных значений, которые (которое) присваивается переменной при объявлении.

Спецификатор класса памяти - определяется одним из четырех ключевых слов языка СИ: auto, register, static, extern и указывает, каким образом будет распределяться память под объявляемую переменную, с одной стороны, а, с другой, область видимости этой переменной, т.е. из каких частей программы можно к ней обратиться.

1.2.1 Категории типов данных

Ключевые слова для определения основных типов данных представлены в таблице 2.1.

Таблица 2.1 - Ключевые слова для определения основных типов данных

Целый тип

Вещественный тип

char

float

int

double

short

long double

long

signed

unsigned

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

Примеры:

const double A=1.23E-2;

const B=456; (подразумевается const int B=456)

Целый тип данных. Для определения данных целого типа используются различные ключевые слова, которые определяют диапазон значений и размер области памяти, выделяемой под переменные (таблица 2.2).

Таблица 2.2 - Диапазон значений и размер области памяти, выделяемой под переменные

Тип

Размер памяти в байтах

Диапазон значений

char

1

от -128 до 127

int

для IBM XT,AT,SX,DX 2

от -32768 до 32767

short

2

от -32768 до 32767

long

4

от -2 147 483 648 до 2 147 483 647

unsigned char

1

oт 0 до 255

unsigned int

2

для IBM XT,AT,SX,DX

unsigned short

2

от 0 до 65535

unsigned long

4

от 0 до 4 294 967 295

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

Например:

unsigned int n;

int c; (подразумевается signed int c );

unsigned d; (подразумевается unsigned int d);

signed f; (подразумевается signed int f).

Отметим, что модификатор-типа char используется для представления символа (из массива представление символов) или для объявления строковых литералов. Значением объекта типа char является код (размером 1 байт), соответствующий представляемому символу. Для представления символов русского алфавита, модификатор типа идентификатора данных имеет вид unsigned char, так как коды русских букв превышают величину 127.

Следует сделать следующее замечание: в языке СИ не определено представление в памяти и диапазон значений для идентификаторов с модификаторами-типа int и unsigned int. Размер памяти для переменной с модификатором типа signed int определяется длиной машинного слова, которое имеет различный размер на разных машинах. Так, на 16-ти разрядных машинах размер слова равен 2-м байтам, на 32-х разрядных машинах, соответственно, 4-м байтам, т.е. тип int эквивалентен типам short int, или long int в зависимости от архитектуры используемой ПЭВМ.

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

Формат операции: sizeof(выражение).

Например:

a = sizeof(int);

b = sizeof(long int);

c = sizeof(unsigned long);

d = sizeof(short);

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

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

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

Например:

0xA8C (int signed);

01786l (long signed);

0xF7u (int unsigned);

Данные плавающего типа. Для переменных, представляющих число с плавающей точкой, используются следующие модификаторы-типа: float, double, long double (в некоторых реализациях языка объявление long double отсутствует).

Величина с модификатором-типа float занимает 4 байта. Из них 1 бит отводится для знака, 8 бит для избыточной экспоненты и 23 бита для мантиссы. Отметим, что старший бит мантиссы всегда равен 1, поэтому он не заполняется, в связи с этим диапазон значений переменной с плавающей точкой приблизительно равен от 3.14E-38 до 3.14E+38.

Величина типа double занимает 8 байт в памяти. Ее формат аналогичен формату float. Биты памяти распределяются следующим образом: 1 бит для знака, 11 бит для экспоненты и 52 бита для мантиссы. С учетом опущенного старшего бита мантиссы диапазон значений равен от 1.7E-308 до 1.7E+308.

Примеры объявления переменных вещественного типа:

float f, a, b;

double x, y;

1.2.2 Инициализация данных

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

Формат 1: = инициатор;

Формат 2: = {список - инициаторов};

Формат 1 используется при инициализации переменных основных типов и указателей, а формат 2 - при инициализации составных объектов.

Примеры:

char n = 'N';

Переменная n инициализируется символом 'N'.

const long megabute = (1024 * 1024);

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

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

char stroka[ ] = "Привет";

Инициализируется массив символов из 7 элементов, последним элементом (седьмым) будет символ '\0', которым завершаются все строковые литералы.

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

Следующее объявление инициализирует переменную stroka как массив, состоящий из семи элементов.

char stroka[5] = "Привет";

В переменную stroka попадают первые пять элементов литерала, а символы 'т' и '\0' отбрасываются.

Если строка короче, чем размер массива, то оставшиеся элементы массива заполняются нулями.

1.3 Выражения и присваивания

1.3.1 Операнды и операции

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

В языке СИ присваивание также является выражением, значением такого выражения является величина, которая присваивается.

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

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

Если в качестве операнда используется константа, то ему соответствует значение и тип представляющей его константы. Целая константа может быть типа int, long, unsigned int, unsigned long, в зависимости от ее значения и от формы записи. Символьная константа имеет тип int. Константа с плавающей точкой всегда имеет тип double. Строковый литерал состоит из последовательности символов, заключенных в кавычки, и представляется в памяти как массив элементов типа char, инициализируемый указанной последовательностью символов. Значением строкового литерала является адрес первого элемента строки и синтаксически строковый литерал является немодифицируемым указателем на тип char. Строковые литералы могут быть использованы в качестве операндов в выражениях, допускающих величины типа указателей. Однако, так как строки не являются переменными, их нельзя использовать в левой части операции присваивания. Следует помнить, что последним символом строки всегда является нулевой символ, который автоматически добавляется при хранении строки в памяти.

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

- идентификаторы объектов целых и плавающих типов представляют значения соответствующего типа;

- идентификатор объекта типа enum представлен значением одной константы из множества значений констант в перечислении. Значением идентификатора является константное значение. Тип значения есть int, что следует из определения перечисления;

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

1. В константных выражениях нельзя использовать операции присваивания и последовательного вычисления (,).

2. Операция "адрес" (&) может быть использована только при некоторых инициализациях.

Выражения со знаками операций могут участвовать в выражениях как операнды. Выражения со знаками операций могут быть унарными (с одним операндом), бинарными (с двумя операндами) и тернарными (с тремя операндами).

Унарное выражение состоит из операнда и предшествующего ему знаку унарной операции и имеет следующий формат:

знак-унарной-операции операнд

Бинарное выражения состоит из двух операндов, разделенных знаком бинарной операции:

операнд 1 знак-бинарной-операции операнд 2 .

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

операнд_1 ? операнд_2 : операнд_3 .

Операции. По количеству операндов, участвующих в операции, операции подразделяются на унарные, бинарные и тернарные.

В языке СИ имеются следующие унарные операции:

- арифметическое отрицание (отрицание и дополнение);

~ побитовое логическое отрицание (дополнение);

! логическое отрицание;

* разадресация (косвенная адресация);

& вычисление адреса;

+ унарный плюс;

++ увеличение (инкремент);

-- уменьшение (декремент);

sizeof размер.

Унарные операции выполняются справа налево.

В отличие от унарных, бинарные операции, выполняются слева направо. Бинарные операции можно классифицировать следующим образом:

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

* - Умножение ;

/ - Деление;

% - Остаток от деления.

Аддитивные

+ - Сложение;

- - Вычитание.

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

<< - Сдвиг влево;

>> - Сдвиг вправо.

Операции отношения

< - Меньше;

<= - Меньше или равно;

>= - Больше или равно;

== - Равно;

!= - Не равно.

Поразрядные операции

& - Поразрядное И ;

| - Поразрядное ИЛИ;

^ - Поразрядное исключающее ИЛИ.

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

&& - Логическое И ;

|| - Логическое ИЛИ.

Последовательного вычисления

, - Последовательное вычисление .

Операции присваивания

= - Присваивание;

*= - Умножение с присваиванием;

/= - Деление с присваиванием;

%= - Остаток от деления с присваиванием;

-= - Вычитание с присваиванием;

+= - Сложение с присваиванием;

<<= - Сдвиг влево с присваиванием;

>>= - Сдвиг вправо присваиванием;

&= - Поразрядное И с присваиванием;

|= - Поразрядное ИЛИ с присваиванием;

^= - Поразрядное исключающее ИЛИ с присваиванием.

Левый операнд операции присваивания должен быть выражением, ссылающимся на область памяти (но не объектом, объявленным с ключевым словом const), такие выражения называются леводопустимыми, к ним в первую очередь относятся:

- идентификаторы данных целого и плавающего типов, типов указателя, структуры, объединения;

При записи выражений следует помнить, что символы (*), (&), (!), (+) могут обозначать унарную или бинарную операцию.

Преобразования при вычислении выражений

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

Рассмотрим общие арифметические преобразования.

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

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

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

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

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

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

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

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

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

Пример:

double ft, sd; unsigned char ch; unsigned long in; int i;

....

sd = ft * (i + ch / in);

При выполнении оператора присваивания правила преобразования будут использоваться следующим образом. Операнд ch преобразуется к unsigned int (правило 5). Затем он преобразуется к типу unsigned long (правило 6). По этому же правилу i преобразуется к unsigned long и результат операции, заключенной в круглые скобки, будет иметь тип unsigned long. Затем он преобразуется к типу double (правило 3) и результат всего выражения будет иметь тип double.

Явное преобразование типов может быть осуществлено посредством операции приведения типов, которая имеет формат:

(имя-типа) операнд

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

Пример:

int i=2; long l=2; double d; float f;

d = (double)i * (double)l;

f = (float)d;

В данном примере величины i, l, d будут явно преобразовываться к указанным в круглых скобках типам.

Рассмотрим некоторые операции языка СИ.

Операция арифметического, логического отрицания и операция дополнения

Операция арифметического отрицания (-)

Пример: int i = 5, k; k = -i; // k =-5

Операция логического отрицания "НЕ" (!) вырабатывает значение 0, если операнд есть истина (не нуль), и значение 1, если операнд равен нулю (0). Результат имеет тип int. Операнд должен быть целого или плавающего типа или типа указатель. Пример: int t, z=0; t=!z; Переменная t получит значение равное 1, так как переменная z имела значение равное 0 (ложно).

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

Пример: int i = 5, k; k = ~i;

При выполнении операции дополнения десятичное число преобразуется в двоичное, инвертируется, добавляется 1 к младшему разряду. В данном случае, десятичное число 5 в двоичном коде есть 101, инверсия этого числа есть -010, в результате будет -011, в десятичном коде - -3. Дополнение - операция определения дополнения до 1.

Пример: char b = '9'; unsigned char f = b, c = ~f;

В результате операции ~f будет получено число, что соответствует символу 'Ж'.

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

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

Примеры:

int t = 1, s = 2, z, f; z = (t++) * 5;

Вначале происходит умножение t*5, а затем увеличение t. В результате получится z=5, t=2.

f = (++s) / 3;

Вначале значение s увеличивается, а затем используется в операции деления. В результате получим s=3, f=1.

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

z++; /* эквивалентно */ ++z;

Мультипликативные операции. К этому классу операций относятся операции умножения (*), деления (/) и получение остатка от деления (%). Операндами операции (%) должны быть целые числа. Отметим, что типы операндов операций умножения и деления могут отличаться, и для них справедливы правила преобразования типов. Типом результата является тип операндов после преобразования.

Операция умножения (*) выполняет умножение операндов.

Пример:

int i = 5;

float f = 0.2;

double g, z;

g = f * i;

Тип произведения i и f преобразуется к типу double, затем результат присваивается переменной g.

Операция деления (/) выполняет деление первого операнда на второй. Если две целые величины не делятся нацело, то результат округляется в сторону нуля.

При попытке деления на ноль выдается сообщение во время выполнения.

Пример:

int i = 49, j = 10, n, m;

n = i / j; /* результат 4 */

m = i / (-j); /* результат -4 */

Операция остаток от деления (%) дает остаток от деления первого операнда на второй.

Знак результата зависит от конкретной реализации. Если второй операнд равен нулю, то выдается сообщение.

Пример:

int n = 49, m = 10, i, j, k, l;

i = n % m; /* 9 */

j = n % (-m); /* 9 */

k = (-n) % m; /* -9 */

Аддитивные операции. К аддитивным операциям относятся сложение (+) и вычитание (-). Операнды могут быть целого или плавающего типов. В некоторых случаях над операндами аддитивных операций выполняются общие арифметические преобразования. Однако преобразования, выполняемые при аддитивных операциях, не обеспечивают обработку ситуаций переполнения и потери значимости. Информация теряется, если результат аддитивной операции не может быть представлен типом операндов после преобразования. При этом сообщение об ошибке не выдается.

Пример:

int i=30000, j=30000, k; k = i + j;

В результате сложения k получит значение равное -5536.

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

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

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

Операция вычитания (-) вычитает второй операнд из первого. Возможна следующая комбинация операндов:

1. Оба операнда целого или плавающего типа.

2. Оба операнда являются указателями на один и тот же тип.

3. Первый операнд является указателем, а второй - целым.

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

Операции сдвига. Операции сдвига осуществляют смещение операнда влево (<<) или вправо (>>) на число битов, задаваемое вторым операндом. Оба операнда должны быть целыми величинами. Выполняются обычные арифметические преобразования. При сдвиге влево правые освобождающиеся биты устанавливаются в нуль. При сдвиге вправо метод заполнения освобождающихся левых битов зависит от типа первого операнда. Если тип unsigned, то свободные левые биты устанавливаются в нуль. В противном случае, они заполняются копией знакового бита. Результат операции сдвига не определен, если второй операнд отрицательный.

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

Отметим, что сдвиг влево соответствует умножению первого операнда на степень числа 2, равную второму операнду, а сдвиг вправо соответствует делению первого операнда на 2 в степени, равной второму операнду.

Примеры:

long int i = 0x1234, j, k ;

k = i << 4 ; /* k = 0x2340 */

j = i << 8 ; /* j = 0x3400 */

Поразрядные операции. К поразрядным операциям относятся: операция поразрядного логического "И" (&), операция поразрядного логического "ИЛИ" (|), операция поразрядного "исключающего ИЛИ" (^).

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

Операция поразрядного логического И (&) сравнивает каждый бит первого операнда с соответствующим битом второго операнда. Если оба сравниваемых бита единицы, то соответствующий бит результата устанавливается в 1, в противном случае в 0.

Операция поразрядного логического ИЛИ (|) сравнивает каждый бит первого операнда с соответствующим битом второго операнда. Если любой (или оба) из сравниваемых битов равен 1, то соответствующий бит результата устанавливается в 1, в противном случае результирующий бит равен 0.

Операция поразрядного исключающего ИЛИ (^) сравнивает каждый бит первого операнда с соответствующими битами второго операнда. Если один из сравниваемых битов равен 0, а второй бит равен 1, то соответствующий бит результата устанавливается в 1, в противном случае, т.е. когда оба бита равны 1 или 0, бит результата устанавливается в 0.

Примеры:

i = 0x45FF, /* i= 0100 0101 1111 1111 */

j = 0x00FF; /* j= 0000 0000 1111 1111 */

r = i ^ j; /* r=0x4500 = 0100 0101 0000 0000 */

r = i | j; /* r=0x45FF = 0100 0101 1111 1111 */

r = i & j /* r=0x00FF = 0000 0000 1111 1111 */

Логические операции. К логическим операциям относятся операция логического И (&&) и операция логического ИЛИ (||). Операнды логических операций могут быть целого типа, плавающего типа или типа указателя, при этом в каждой операции могут участвовать операнды различных типов. Операнды логических выражений вычисляются слева направо. Если значения первого операнда достаточно, чтобы определить результат операции, то второй операнд не вычисляется. Логические операции не вызывают стандартных арифметических преобразований. Они оценивают каждый операнд с точки зрения его эквивалентности нулю. Результатом логической операции является 0 или 1, тип результата int.

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

Операция логического ИЛИ (||) выполняет над операндами операцию включающего ИЛИ. Она вырабатывает значение 0, если оба операнда имеют значение 0, если какой-либо из операндов имеет ненулевое значение, то результат операции равен 1. Если первый операнд имеет ненулевое значение, то второй операнд не вычисляется.

Составное присваивание. Кроме простого присваивания, имеется целая группа операций присваивания, которые объединяют простое присваивание с одной из бинарных операций. Такие операции называются составными операциями присваивания и имеют вид:

(операнд_1) (бинарная операция) = (операнд_2) .

Составное присваивание по результату эквивалентно следующему простому присваиванию:

(операнд_1) = (операнд_1) (бинарная операция) (операнд_2) .

Отметим, что выражение составного присваивания, с точки зрения реализации, не эквивалентно простому присваиванию, так как в последнем случае операнд_1 вычисляется дважды.

Каждая операция составного присваивания выполняет преобразования, которые осуществляются соответствующей бинарной операцией. Левым операндом операций (+=) (-=) может быть указатель, в то время как правый операнд должен быть целым числом.

Примеры:

double a = 2.0;

double b=3.0;

b+=a; /* эквивалентно b=b+a */

Условная операция. В языке СИ имеется одна тернарная операция - условная операция, которая имеет следующий формат:

операнд_1 ? операнд_2 : операнд_3

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

1. Если операнд_2 или операнд_3 имеет целый или плавающий тип (отметим, что их типы могут отличаться), то выполняются обычные арифметические преобразования. Типом результата является тип операнда после преобразования.

2. Если операнд_2 и операн_3 имеют один и тот же тип структуры, объединения или указателя, то тип результата будет тем же самым типом структуры, объединения или указателя.

3. Если оба операнда имеют тип void, то результат имеет тип void.

4. Если один операнд является указателем на объект любого типа, а другой операнд является указателем на vold, то указатель на объект преобразуется к указателю на vold, который и будет типом результата.

5. Если один из операндов является указателем, а другой константным выражением со значением 0, то типом результата будет тип указателя.

Пример:

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

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

1.3.2 Приоритеты операций и порядок вычислений

В языке СИ операции с высшими приоритетами вычисляются первыми. Наивысшим приоритетом является приоритет, равный 1 (табл. 1.3).

Таблица 1.3 - Приоритеты операций

Приоритет

Знак операции

1.

~ ! * & ++ -- sizeof приведение типов

2.

() [] . ->

3.

* / %

4.

+ -

5.

<< >>

6.

< > <= >=

7.

== !=Отношение (равенство)

8.

& Поразрядное И

9.

^ Поразрядное исключающее ИЛИ

10.

| Поразрядное ИЛИ

11.

&& Логическое И

12.

|| Логическое ИЛИ

13.

? : Условная

14.

= * = / = % = + = - = & = | = >> = << = ^ =

15.

, Последовательное вычисление

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

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

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

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

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

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

1.4 Операторы

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

- оператор "выражение", пустой оператор и др.;

- условные операторы, к которым относятся:

- оператор условия if и оператор выбора switch;

- операторы цикла (for,while,do while);

- операторы перехода (break, continue, return, goto);

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

Все операторы языка СИ, кроме составных операторов, заканчиваются точкой с запятой ";".

1.4.1 Оператор выражение

Любое выражение, которое заканчивается точкой с запятой, является оператором. Выполнение оператора выражение заключается в вычислении выражения. Полученное значение выражения никак не используется, поэтому, как правило, такие выражения вызывают побочные эффекты. Заметим, что вызвать функцию, невозвращающую значения можно только при помощи оператора выражения. Правила вычисления выражений были сформулированы выше.

Примеры:

++ i;

Этот оператор представляет выражение, которое увеличивает значение переменной i на единицу.

a=cos(b * 5);

Этот оператор представляет выражение, включающее в себя операции присваивания и вызова функции.

a(x,y);

Этот оператор представляет выражение, состоящее из вызова функции.

1.4.2 Пустой оператор

Пустой оператор состоит только из точки с запятой. При выполнении этого оператора ничего не происходит. Он обычно используется в следующих случаях:

- в операторах do, for, while, if в строках, когда оператор не требуется, но по синтаксису требуется хотя бы один оператор;

- при необходимости пометить фигурную скобку.

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

Пример: int main ( ) {

:

{

if (...) goto a; /* переход на скобку */

{ ... }

a:;

}

return 0; }

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

1.4.3 Составной оператор

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

{ [oбъявление]

:

оператор; [оператор];

: }

Заметим, что в конце составного оператора точка с запятой не ставится.

Выполнение составного оператора заключается в последовательном выполнении составляющих его операторов.

1.4.4 Условные операторы

Оператор if

Формат оператора:

if (выражение) оператор_1; [else оператор_2;]

Выполнение оператора if начинается с вычисления выражения.

Далее выполнение осуществляется по следующей схеме:

- если выражение истинно (т.е. отлично от 0), то выполняется оператор_1.

- если выражение ложно (т.е. равно 0), то выполняется оператор_2.

- если выражение ложно и отсутствует оператор_2 (в квадратные скобки заключена необязательная конструкция), то выполняется следующий за if оператор.

После выполнения оператора if значение передается на следующий оператор программы, если последовательность выполнения операторов программы не будет принудительно нарушена использованием операторов перехода.

Пример:

if (i < j) i++;

else { j = i - 3; i++; }

Этот пример иллюстрирует также и тот факт, что на месте оператор_1, так же как и на месте оператор_2 могут находиться сложные конструкции.

Допускается использование вложенных операторов if. Оператор if может быть включен в конструкцию if или в конструкцию else другого оператора if. Чтобы сделать программу более читабельной, рекомендуется группировать операторы и конструкции во вложенных операторах if, используя фигурные скобки. Если же фигурные скобки опущены, то компилятор связывает каждое ключевое слово else с наиболее близким if, для которого нет else.

Примеры:

int main ( ) { int t = 2, b = 7, r = 3;

if (t > b)

{

if (b < r) r = b;

}

else r = t;

return (0); }

В результате выполнения этой программы r станет равным 2.

Если же в программе опустить фигурные скобки, стоящие после оператора if, то программа будет иметь следующий вид:

int main ( )

{

int t = 2, b = 7, r = 3;

if ( t > b )

if ( b < r ) r = b;

else r = t;

return (0);

}

В этом случае r получит значение равное 3, так как ключевое слово else относится ко второму оператору if, который не выполняется, поскольку не выполняется условие, проверяемое в первом операторе if.

Следующий фрагмент иллюстрирует вложенные операторы if:

char ZNAC;

int x, y, z;

:

if (ZNAC == '-') x = y - z;

else if (ZNAC == '+') x = y + z;

else if (ZNAC == '*') x = y * z;

else if (ZNAC == '/') x = y / z;

else ...

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

Другим способом организации выбора из множества различных вариантов является использование специального оператора выбора switch.

Оператор switch

Оператор switch предназначен для организации выбора из множества различных вариантов. Формат оператора следующий:

switch (выражение)

{ [объявление]

:

[case константное-выражение1]: [ список-операторов1]

[case константное-выражение2]: [ список-операторов2]

:

:

[default: [ список операторов ]]

}

Выражение, следующее за ключевым словом switch в круглых скобках, может быть любым выражением, допустимыми в языке СИ, значение которого должно быть целым. Отметим, что можно использовать явное приведение к целому типу, однако, необходимо помнить о тех ограничениях и рекомендациях, о которых говорилось выше.

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


Подобные документы

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

    контрольная работа [31,2 K], добавлен 12.12.2009

  • Элементы языка Object Pascal: идентификаторы, константы, переменные, выражения. Структура проекта Delphi. Операторы и метки. Типы данных языка OPascal. Статические и динамические массивы. Записи с вариантными полями. Совместимость и преобразование типов.

    курс лекций [385,4 K], добавлен 18.02.2012

  • Понятие и общая характеристика языка программирования РНР, принципы и этапы его работы, синтаксис и ассоциируемые массивы. Обработка исключений в языке Java. Работа с базами данных с помощью JDBC. Изучение порядка разработки графического интерфейса.

    презентация [192,3 K], добавлен 13.06.2014

  • Лингвистическая концепция языка Паскаль. Интегрированная инструментальная оболочка. Основы построения программ на ТП 7.0. Алфавит языка и специфика использования символов. Простые типы данных: константы и переменные. Циклические конструкции и операции.

    курсовая работа [284,6 K], добавлен 02.07.2011

  • Конструкции Си, базовые типы данных языка программирования. Идентификаторы и типизированные константы. Область видимости и время жизни переменных. Функции преобразования символьных строк. Функции, работающие со строками. Разработка визуальных компонент.

    методичка [400,2 K], добавлен 06.07.2009

  • История создания и применение языка Basic. Стандартные математические и строковые функции. Операции и выражения языка. Блоки данных и подпрограммы. Операторы управления, цикла, ввода-вывода и преобразования информации. Константы, переменные, массивы.

    контрольная работа [2,3 M], добавлен 04.05.2015

  • Элементы и переменные, используемые для составления записи в Паскале. Основные числовые типы языка Turbo Pascal. Составление блок-схемы приложения, программирование по ней программы для вычисления функции. Последовательность выполнения алгоритма.

    лабораторная работа [256,9 K], добавлен 10.11.2015

  • Понятие алгоритма. Цикл программы. Структурная схема алгоритма. Элементы языка Тurbo Рascal. Алфавит. Идентификаторы. Комментарии. Лексика языка С++. ESC-последовательности. Операции. Ключевые слова. Комментарии.

    контрольная работа [43,0 K], добавлен 24.04.2006

  • Основы языка программирвоания C++. Элементы управления в Microsoft Visual C++. Алгоритмические конструкции языка программирования Visual C++ и базовые элементы управления. Глобальные константы и переменные. Управление программой с помощью клавиатуры.

    курсовая работа [1,7 M], добавлен 08.04.2015

  • Метод половинного деления и метод касательных. Переменные, константы, объявление типов данных. Объект WorkBook: его свойства, методы и события. Методы нахождения корней уравнений. Структурированные типы данных. Терминальные свойства объекта Workbook.

    курсовая работа [1,1 M], добавлен 14.07.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.