Константы 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; просмотров: 711;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.135 сек.