- •Обзорные лекции по курсу
- •Int Temp[12] - {2, 4, 7, } ;
- •Int main ()
- •Разыменование указателей
- •Int main()
- •Void *ptr;
- •Int main ()
- •Int main ()
- •Int main ()
- •Void *malloc(size_t size);
- •Void *calloc( size_t num, size_t size );
- •Void free(void *block);
- •Int main(void)
- •Int* pRegion;
- •Void newHandler()
- •Int main()
- •Int main ()
- •Int strcmp(const char* strl, const char* str2)
- •Int stricmp(const char* strl, const char* str2)
- •Int strncmp(const char* strl,
- •Int strnicmp(const char* strl,
- •Void *malloc(size_t size);
- •Void *calloc( size_t num, size_t size );
- •Void free(void *block);
- •Int main(void)
- •Int* pRegion;
- •Int main ()
- •Упражнения для самопроверки
Int Temp[12] - {2, 4, 7, } ;
Таким образом, элементы Теmр[0], Теmр[1] и Теmр[2] будут проинициализированы, в то время как оставшиеся элементы инициализации не получат.
При объявлении одномерного массива с одновременной его инициализацией разрешается опускать значение размера, обычно указываемое в квадратных скобках. При этом компилятор самостоятельно подсчитает количество элементов в списке инициализации и выделит под них необходимую область памяти:
// Выделение в памяти места для хранения
// шести объектов типа int
// (24 байта для 32-разрядной системы)
int Even[] = {0, 2, 4, 6, 8, 10};
Если далее в программе потребуется определить, сколько элементов имеется в массиве, можно воспользоваться следующим выражением:
int Size = sizeof(Even)/sizeof(Even[O]);
Здесь выражение sizeof(Even) определяет общий размер, занимаемый массивом Even в памяти (в байтах), а выражение sizeof (Even[0]) возвращает размер (тоже в байтах) одного элемента массива.
В многомодульном проекте инициализация массива при объявлении производится лишь в одном из модулей. В других модулях получить доступ к элементам массива можно с помощью ключевого слова extern:
// Модуль first.срр
...
char Hello[] = {'Н','е', '1', '1','о'} ;
...
// Модуль second.срр
extern Hello[];
// Модуль n.срр extern Hello[5];
Попытка повторной инициализации вызовет сообщение компилятора об ошибке.
Понятие указателя
Любой объект программы, будь то переменная базового или же производного типа, занимает в памяти определенную область. Местоположение объекта в памяти определяется его адресом. Как уже говорилось, при объявлении переменной для нее резервируется место в памяти, размер которого зависит от типа данной переменной, а для доступа к содержимому объекта служит его имя (идентификатор). Для того чтобы узнать адрес конкретной переменной, служит унарная операция взятия адреса. При этом перед именем переменной ставится знак амперсанда (&). Следующий ниже пример программы выведет на печать сначала значение переменной Vl и V2, а затем ее адрес:
#include <iostream.h>
#define end1 '\n'
Int main ()
{
unsigned int Vl = 40000;
unsigned int V2 = 300;
cout « "Значение1: " « Vl « endl;
cout « "Адрес : " « &Vl « endl;
oout « 3начение2: " « V2 « endl;
cout « "Адрес ; " « &V2 « endl;
return 0;
}
В результате будет выведено:
Значение1: 40000 Адрес : Ox0068feOO
Значение2: 300
Адрес : Ox0068fdfc
Как видно из примера, адреса локальных переменных, размещаемых в стеке, следуют в обратном порядке (стек растет в направлении младших адресов). Результат может отличаться даже при повторном запуске программы, так как невозможно предугадать, по какому адресу начнут размещаться переменные. Важно другое: разница в адресах первой и второй переменной всегда будет одинакова и при четырехбайтном представлении типа int составит 4 байта (см. рис. 4.1).
Рис. 4.1. Размещение переменных в памяти
Мощным средством разработчика программного обеспечения на C++ является возможность непосредственного доступа к памяти. Для этой цели предусматривается специальный тип переменных - указатели.
Указатель (pointer) представляет собой переменную, значение которой является адресом ячейки памяти. Указатель может ссылаться на переменную (базового или производного типа) или функцию. Наибольшая эффективность применения указателей в разработке приложений достигается при использовании их с массивами и символьными строками.
Объявление указателя имеет следующий синтаксис:
тип объекта* идентификатор;
Здесь тип_объекта определяет тип данных, на которые ссылается указатель с именем идентификатор. Символ 'звездочка' (*) сообщает компилятору, что объявленная переменная является указателем и не зависимо от того, сколько памяти требуется отвести под сам объект, для указателя резервируется два или четыре байта в зависимости от используемой модели памяти.
Рис. 4.2. Схема работы указателя
Поскольку указатель представляет собой ссылку на некоторую область памяти, ему может быть присвоен только адрес некоторой переменной (или функции), а не само ее значение. В случае некорректного присвоения компилятор выдаст соответствующее сообщение об ошибке.
Рассмотрим пример объявления и инициализации указателя.
char Symbol = ' Y' ;
char *pSymbol = &Symbol;//Указатель *pSymbol инициализируется
//адресом переменной Symbol
long Capital = 304L;
long* pLong;
pLong = &Capital;
В приведенном фрагменте объявляется символьная переменпая Symbol и инициализируется значением 'Y', затем определяется указатель на символьный тип данных pSymbol, значение которого назначается равным адресу переменной Symbol. Вслед за этим объявляется переменная capital типа long и указатель на этот же тип pLong, после чего производится инициализация указателя адресом переменной Capital.