Константы 1 страница
Константы — неизменяемые величины.
Как показано в табл. 3.2, константы бывают:
— целые;
— вещественные (с плавающей запятой);
— символьные;
— строковые.
Таблица 3.2 — Форматы констант
Константа | Формат | Примеры |
Целая | Десятичный: Последовательность десятичных цифр (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) | 8, 0, 1265, 19912 |
Восьмеричный: Нуль, за которым следуют восьмерич-ные цифры (0, 1, 2, 3, 4, 5, 6, 7) | 01, 020, 075346 | |
Шестнадцатеричный: 0х или 0Х, за которыми следуют шестнадцатеричные цифры (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F) | 0хА, 0х1B8, 0X40FA | |
Вещественная | Десятичный: [цифры].[цифры] | 5.7, .001, 34 |
Экспоненциальный: | 0.25E6, 0.11e–4, 5e3 | |
Символьная | Один или два символа, заключенные в апострофы | 'A', 'ю', 'дБ', '\' |
Строковая | Последовательность символов, заключенная в кавычки | ''Здесь был Федя'', ''Значения перемен-ной'' |
Замечания.
Для формирования отрицательной целой или вещественной константы используется знак «–» (минус).
В экспоненциальном виде число имеет следующий вид
мантисса Е порядок
.
Символьные константы, состоящие из одного символа занимают в памяти один байт (и имеют тип char).
Двухсимвольные константы занимают два байта (и имеют тип int). Первый символ размещен в байте с меньшим адресом.
В строковых константах могут быть использованы управляющие последовательности символов.
Последовательность символов, начинающуюся с обратной косой черты, называют управляющей. Основные символы данного вида представлены в табл. 3.3.
Таблица 3.3 — Управляющие последовательности в языке С/С++
Последова-тельность | Шестнадцате-ричный код | Назначение |
\a | Звуковой сигнал | |
\b | Возврат на шаг | |
\f | 00С | Перевод страницы |
\n | 00A | Перевод строки |
\r | 00D | Возврат каретки |
\t | Горизонтальная табуляция | |
\v | 00B | Вертикальная табуляция |
\\ | 05C | Обратная косая черта |
\’ | Апостроф | |
\’’ | Кавычки | |
\? | 03F | Вопросительный знак |
\0ddd | — | Восьмеричный код символа |
\0xddd | ddd | Шестнадцатеричный код символа |
Если за обратной косой чертой стоит символ, не указанный в таблице, то результат интерпретации не определён.
Управляющие последовательности могут быть использованы в строковых константах. Например, если внутри строки требуется заплатить кавычку, её предваряют косой чертой:
''Произведение\''Война и мир\'' ''
Если строковые константы разделены только пробелом, то они воспринимаются как одна константа. Длинные строковые константы можно размещать на нескольких строках:
''Севастопольский национальный технический университет \
(СевНТУ)''
3.2.4. Ключевые слова
Ключевые слова — это зарезервированные идентификаторы, которые имеют специальное значение для компилятора.
Таблица 3.4 — Список ключевых слов
asm | enum | new | throw | unsigned |
auto | explicit | operator | true | using |
bool | export | private | try | virtual |
break | extern | protected | typedef | void |
case | false | public | typeid | volatile |
catch | float | register | typename | wchar_t |
char | for | return | union | while |
class | friend | short | ||
const | goto | signed | ||
continue | if | sizeof | const_cast | |
default | inline | static | dynamic_cast | |
delete | int | struct | reinterpret_cast | |
do | long | switch | static_cast | |
double | mutable | template | ||
else | namespace | this |
Эти слова можно использовать только в том значении, в котором они определены.
3.2.5. Знаки операций
Знаки операций — это один или более символов, определяющих действие над операндами.
Пробелы внутри знака операции не допускаются.
По количеству участвующих в них операндов операции делятся на унарные, бинарные и тринарные. Один и тот же знак в различных ситуациях может истолковываться по-разному. В таблице 3.5 представлены основные операции языка С++.
Таблица 3.5 — Основные операции языка С++
Операции | Краткое описание |
Унарные операции | |
++ | Инкремент (увеличение на 1) |
– – | Декремент (уменьшение на 1) |
sizeof | Размер |
~ | Поразрядное отрицание |
! | Логическое отрицание |
– | Унарный минус (арифметическое отрицание) |
+ | Унарный плюс |
& | Взятие адреса |
* | Реадресация |
new | Выделение памяти |
delete | Освобождение памяти |
type | Преобразование типа |
Бинарные и тернарная операции | |
* | Умножение |
/ | Деление |
% | Остаток от деления |
+ | Сложение |
– | Вычитание |
<< | Сдвиг влево |
>> | Сдвиг вправо |
< | Меньше |
<= | Меньше или равно |
> | Больше |
>= | Больше или равно |
== | Равно |
!= | Не равно |
& | Поразрядная конъюнкция (И) |
| | Поразрядная дизъюнкция (ИЛИ) |
^ | Поразрядное исключающее ИЛИ |
&& | Логическое И |
|| | Логическое ИЛИ |
?: | Условная операция (тернарная) |
Операции присваивания | |
= | Присваивание |
*= | Умножение с присваиванием |
/= | Деление с присваиванием |
%= | Остаток от деления с присваиванием |
+= | Сложением с присваиванием |
–= | Вычитание с присваиванием |
<<= | Сдвиг влево с присваиванием |
>>= | Сдвиг вправо с присваиванием |
Продолжение таблицы 3.5
Операции | Краткое описание |
&= | Поразрядное И с присваиванием |
|= | Поразрядное ИЛИ с присваиванием |
^= | Поразрядное исключающее ИЛИ с присваиванием |
, | Последовательное вычисление |
3.2.6. Комментарии
Комментарии — последовательность символов, игнорируемая компилятором.
Начинается комментарий либо с двух символов «косая черта» (//) и заканчивается символом перехода на новую строку, либо заключается между символами /* */ .
Замечание. Вложенные комментарии не допускаются.
Пример,
3.3. Лекция 6. Типы данных и их объявление
3.3.1. Основные типы данных
В языке С/С++ все переменные, используемые в программе, необходимо объявлять. Тоже самое касается констант. Объявление связано с необходимостью выделить под переменную или константу область памяти, размер которой определяется задаваемым типом данных.
Основные (стандартные) типы данных часто называют арифметическими, поскольку их можно использовать в арифметических операциях:
Целочисленные типы:
Типы с плавающей запятой:
Диапазоны значений, которые могут принимать переменные представленных типов, приведены в таблице 3.6.
Таблица 3.6 — Диапазоны значений простых типов данных
Тип | Диапазон значений | Размер, байт |
bool | true и false | |
signed char | –128 … 127 | |
unsigned char | 0 … 255 | |
signed short int | –32 768 … 32 767 | |
unsigned short int | 0 … 65 535 | |
signed long int | –2 147 483 648 … 2 147 483 647 | |
unsigned long int | 0 … 4 294 967 295 | |
float | 3.4e–38 … 3.4e+38 | |
double | 1.7e–308 … 1.7e+308 | |
long double | 3.4e–4932 … 3.4e+4932 |
Примечания:
1. Размер типа int определяется при объявлении типом процессора (ЦПУ). Для 16-разрядного ЦПУ — 2 байта (16 бит) и для 32-разрядного — 4 байта (32 бита).
2. Выбор типа short int указывает компилятору, что под переменную требуется 2 байта независимо от ЦПУ.
Выбор типа long int — указывает, что требуется 4 байта независимо от ЦПУ.
3. Типы констант могут быть обозначены суффиксами:
L , l — long int ; long double ;
U , u — unsigned int ;
F , f — float .
Например: 32L — тип long int;
32ul — тип unsigned long int;
2E+6L — тип long double;
1.82f — тип float.
4. Для различных ПК и ОС нельзя делать предположение о размерах памяти, занимаемых различными типами переменных. Необходимо определять эту величину операцией sizeof.
Например:
a=sizeof(int) ;
Результатом операции будет число 2 (в байтах) для MS-DOS, и
4 для Windows или OS/2.
5. Целые типы short int, long int,
signed int и unsigned int
можно сокращать до
short, long,
signed и unsigned.
6. Минимальные и максимальные допустимые значения приводятся в заголовочных файлах float.h (для вещественных) и limits.h (для целых переменных).
3.3.2. Объявление типов данных
Объявления С/С++ в имеют следующий формат записи (квадратные скобки показывают, что элемент может отсутствовать):
[спецификатор_класса_памяти] [const] [спецификатор_типа] [тип]
описатель [инициатор] [, описатель [инициатор] ] … ;
Здесь:
— [спецификатор_класса_памяти] — определяется одним из 4 классов и определяет, каким образом будет распределяться память под переменную и область видимости переменной:
auto — автоматические переменные; являются локальными для каждого вызова блока и исчезают при выходе из этого блока; не используется для глобальных переменных, для локальных устанавливается по умолчанию;
extern — внешние переменные; существуют и сохраняют свои значения в течение выполнения всей программы и могут использоваться для связи между функциями, в том числе и между независимо скомпилированными функциями;
static — статические переменные; являются локальными, но могут быть и глобальными; сохраняют свои значения после того, как управление передаётся за пределы блока;
register — регистровые переменные; хранятся (если это возможно) в быстрых регистрах процессора; являются локальными для каждого блока и исчезают при выходе из этого блока; если в регистры нет возможности поместить переменную, то она обрабатывается как auto.
— [const] — модификатор, указывающий на то, что значение переменной изменять нельзя, т.е. переменная является именованной константой;
— [спецификатор_типа] — уточняет внутреннее представление и диапазон значений типов:
short — короткий;
long — длинный;
signed — знаковый;
unsigned — беззнаковый;
— [тип] — указывает на тип переменной;
bool — целый тип;
char — символьный тип;
int — целый тип;
float — вещественный тип;
double — вещественный тип с двойной точностью;
— описатель — (имя переменной) идентификатор простой переменной, либо более сложная конструкция (с квадратными скобками, круглыми скобками, одной или несколькими звёздочками);
— [инициатор] — присвоение переменной начального значения при инициализации; существуют две формы записи:
=значение — присвоение значения с использованием знака равенства;
(значение) — присвоение значения с использованием круглых скобкок.
В одном операторе можно описать несколько переменных одного типа, разделяя их запятыми.
Примеры:
1)
short int a=1 ; // короткая целая a=1
int b (7) ; // целая b=7
float c=0.22 , //переменная с плавающей запятой c=0,22
x (3) , // переменная с плавающей запятой x=3
s ; // переменная с плавающей запятой
2)
int a ; // глобальная переменная
main ()
{
int b ; // локальная переменная b
extern int x ; // x определена в другом месте
static int y ; // статическая переменная y
a=1 ; // присвоение локальной переменной а
b=2 ; // присвоение локальной переменной b
:: a=3 ; //присвоение глобальной переменной
return 0 ;
}
int x=4 ; // присвоение и инициализация переменной х
3.4. Лекция 7. Указатели и массивы
3.4.1. Объявление указателей
При обработке оператора определения переменной, например, int i = 10 ; компилятор выделяет память в соответствие с типом (int) и инициализирует её с указанным значением (10). Все обращения в программе к переменной по её имени (i) заменяются компилятором на адрес области памяти, в которой хранится значение переменной.
Программист может определить собственные переменные для хранения адресов областей памяти. Такие переменные называются указателями.
Указатели — это переменные, предназначенные для хранения адресов областей памяти.
Различают три вида указателей:
— указатели на функцию;
— указатели на объект;
— указатели на void.
Указатель на функцию содержит адрес области памяти в сегменте кода, по которому располагается исполняемый код функции.
Используется для:
— косвенного вызова функции (не через имя, а через обращение к переменной, хранящей ее адрес);
— передачи имени функции в другую функцию в качестве параметра.
Формат записи указателя на функцию имеет вид:
тип (*имя) (список_типов_аргументов);
Например, объявление вида:
int (*cooler) (double, double);
задаёт указатель cooler на функцию, возвращающую значение типа int и имеющую два аргумента типа double.
Указатель на объект содержит адрес области памяти, в которой хранятся данные основного или составного типа.
Формат указателя на объект в простейшем варианте имеет вид:
тип *имя;
где: тип — может быть любым типом, кроме ссылки и битового поля;
* — относится к имени.
Например:
int *a, b, *c ;
В данном примере описываются два указателя на целое с именами a и c, а также целая переменная b. Размер указателя зависит от модели памяти. Можно определить указатель на указатель и т.д.
Указатель на void применяется в тех случаях, когда конкретный тип объекта, адрес которого требуется хранить, не определен (например, если в одной и той же переменной в разные моменты времени требуется хранить адреса объектов различных типов).
Форматы указателя на void имеют вид:
тип (*имя) (список_типов_аргументов);
тип *имя;
Примечание (!):
Указателю на void можно присвоить значение указателя любого типа, сравнивать его с любыми указателями, но перед выполнением действий с областью памяти, на которую он ссылается, требуется преобразовать его к конкретному типу явным образом.
Примеры объявления указателей:
1) int i ; // целая переменная
2) const int ci=1 ; // целая константа
3) int *pi ; // указатель на целую переменную
4) const int *pci ; // указатель на целую константу
5) int *const cp=&i ; // указатель-константа на целую
// переменную
6) const int *const cpc=&ci ; // указатель константа на
// целую константу
В представленных примерах:
1) символ & — команда взятия адреса переменной;
2) модификатор const — запрещает изменение значения указателя;
const — указывает на то, что в ячейке памяти хранится
константа.
3.4.2. Инициализация указателей
Указатели чаще всего используют при работе с динамической памятью (кучей).
Динамическая память — свободная память, в которой можно во время выполнения программы выделять место под данные в соответствии с потребностями.
Доступ к выделенным участкам динамической памяти, называемым динамическими переменными, производится только через указатели.
Время «жизни» динамических переменных — от момента объявления, до конца выполнения программы или до явного освобождения динамической памяти.
В С/С++ используют два способа работы с динамической памятью:
— используя семейство функций malloc;
— используя операции new и delete.
Примечание! При объявлении указателей рекомендуется выполнять их инициализацию. |
Инициализатор записывается после имени указателя либо в круглых скобках, либо после знака равенства.
Способы инициализации указателей:
— присваивание указателю адреса уже существующего объекта;
— присваивание указателю адреса области памяти в явном виде;
— присваивание пустого значения;
— выделение (и освобождение) участка динамической памяти и присваивание её адреса указателя.
1. Присвоение указателю адреса существующего объекта:
— с помощью операции получения адреса:
int a=5 ; // целая переменная
int *p=&a ; // в указатель записывается адрес
// переменной “а”
int *p (&a) ; // в указатель записывается адрес
// переменной “а” другим способом
— с помощью значения другого инициализированного указателя:
int *r=p ; //p — указатель, унициализированный ранее
— с помощью имени массива или функции, которые трактуются как адрес:
int b[10] ; // объявление массив
int *t=b ; // присваивание адреса начала массива
…
void f(int a) { … } // определение функции
void (*pf)(int) ; // объявление указателя на функцию
pf=f // присваивание указателю адреса
// функции
2. Присваивание указателю адреса области памяти в явном виде:
char *vp=(char*) 0xB8000000 ;
Здесь 0xB8000000 — шестнадцатеричная константа (адрес области памяти);
(char*) — операция приведения типа: константа преобразуется к типу «указатель на char».
3. Присваивание пустого значения:
int *a=NULL ;
int *b=0 ; // рекомендуется использовать этот вариант
Здесь NULL — нулевая константа.
Так как объектов с нулевым адресом нет, то пустой указатель можно использовать для проверки, ссылается ли проверяемый указатель на какой-либо объект или нет.
Рекомендуется использовать второй вариант инициализации.
4. Выделение участка динамической памяти и присваивание её адреса указателю:
Пример:
— с помощью new:
int *n=new int ; // 1
int *m=new int (10) ; // 2
int *q=new int [10] ; // 3
— с помощью функции malloc (библиотека <malloc.h>):
int *u=(int*) malloc(sizeof(int)) ; // 4 .
В представленных примерах инструкции могут быть описаны следующим образом:
//1 — операция new выполняет выделение достаточного для размещения величины типа int участка динамической памяти и записывает адрес начала этого участка в переменную n.
Память под саму переменную n (размера, достаточного для размещения указателя) выделяется на этапе компиляции.
//2 — выполняются действия, описанные выше, а также производится инициализация выделенной динамической памяти значением 10.
//3 — операция new выполняет выделение памяти под 10 величин типа int (т.е. под массив из 10-ти элементов) и записывает адрес начала этого участка в переменную q , которая может трактоваться как имя массива, через которое можно обращаться к любому элементу массива.
//4 — выполняется тоже самое, что в //1, но с помощью функции malloc . В функцию передаётся один параметр — количество выделяемой памяти в байтах.
(int*) — приведение типа указателя, возвращаемого функцией, к требуемому типу. Функция возвращает 0, если выделить память не удалось.
Примечание (!):
Предпочтительнее использовать операцию new, чем функцию malloc, особенно при работе с объектами.
5. Освобождение памяти:
— выделение new — освобождение delete;
— выделение malloc — освобождение free.
Пример освобождения памяти (соответствует примеру выделения памяти): delete n ; // 1
delete m ; // 2
delete []q ; // 3
free(u) ; // 4
Примечания:
Если выделение осуществлялось для массива, то необходимо указывать, что освобождается массив, поставив перед именем указателя пустые квадратные скобки (для освобождения требуется []delete). Размерность массива при этом не указывается.
Если нет скобок [], то освобождается только первый элемент массива, а остальные окажутся недоступными для дальнейших операций. Т.е. появляется «мусор» в памяти.
«Мусор» также может появиться, когда переменная-указатель выходит из области своего действия (и становиться недоступной), или когда инициализированному указателю присваивается значение другого указателя (старое значение теряется).
3.4.3. Составные указатели
Пример:
Здесь объявляется массив из 10 указателей на функции без параметров, возвращающих указатели на int.
По умолчанию скобки [] и () имеют одинаковый приоритет, больший, чем * и рассматриваются слева направо. Для изменения порядка используют круглые скобки. Таким образом, порядок приоритета в приведенном примере составного указателя показан цифрами снизу.
Для сложных описаний используют правило «изнутри наружу»:
1) если справа от имени '[]' — это массив,
если '()' — функция;
2) если слева '*', то это указатель на проинтерпретированную ранее конструкцию;
3) если справа встречается ')', то необходимо применить приведённые выше правила внутри скобок, а затем переходить наружу;
4) в последнюю очередь интерпретируется спецификатор типа.
3.4.4. Операции над указателями
Над указателями разрешается выполнять следующие операции:
— реадресация или косвенное обращение к объекту (*);
— присваивание;
— сложение с константой;
— вычитание;
— инкремент (++);
— декремент (– –);
— сравнивание;
— приведение типов.
Кроме выше перечисленных операций, часто используется операция взятия адреса (&).
Операция реадресации — предназначена для доступа к величине, адрес которой хранится в указателе. Операцию можно использовать для получения и изменения величины.
Пример:
char a ; // объявление переменной типа char
char *p=new char ; // выделение памяти под указатель и
// под динамическую переменную типа char
*p=''Ю'' ; a=*p ; // присваивание значения обеим переменным
На одну и ту же область памяти может ссылаться несколько указателей различных типов.
Пример:
…
unsigned long int A=0Xcc77ffaa ;
unsigned short int *p_int=(unsigned short int*) &A ;
unsigned char *p_char=(unsigned char *) &A;
…
printf(''| %x | %x | %x |'' , A , *p_int , *p_char);
… }
Результат выполнения:
| cc77ffaa | ffaa | aa |
Примечание.
Присваивание без приведения типов допускается для указателей:
— типа void*;
— одного типа.
Арифметические операции с указателями — сложение с константой, вычитание, инкремент, декремент.
Операции применимы только к указателям одного типа и имеют смысл при работе со структурами данных (массивами).
Операции автоматически учитывают размер типов величин, адресуемых указателями.
Операции умножения, деления или сложения указателей не существует!
Инкремент — ++ перемещает указатель к следующему элементу структуры данных (массива).
Декремент — – – перемещает указатель к предыдущему элементу.
Значение указателя изменяется на величину sizeof(тип) в байтах.
Пример:
short *p=new short[5] ; //объявление указателя на массив
p++ ; // массив p увеличивается на 2 (байта)
long *q=new long[5] ; // объявление указателя на массив
q++ ; // q увеличивается на 4 (байта)
Разность двух указателей — это разность их значений, делённая на размер типа в байтах.
Например, разность указателя на 3-й элемент массива и на 6-й элемент равна 3.
При сложении с константой или других действиях следует учитывать приоритеты выполнения операций.
Примечание! Суммирование указателей не допускается. |
Пример:
1) *p++=10 ; /* Û */ *p=10 ; p++ ;
// Два одинаковых по смыслу выражения,
// в которых вначале по адресу *p запишется 10,
// а потом указатель увеличивается на 1xsizeof(тип).
2) (*p)++; // Выражение увеличивает содержимое ячейки памяти.
Операция получения (взятия) адреса & — применима к величинам, имеющим имя и размещенным в ОЗУ.
Нельзя получить адрес скалярного выражения, неименованной константы, регистровой переменной.
3.4.5. Ссылки
Дата добавления: 2015-10-21; просмотров: 768;