Тип void
Тип void (пустой) синтаксически ведет себя как основной тип. Однако использовать его можно только как часть производного типа, объектов типа void не существует. Он используется для того, чтобы указать, что функция не возвращает значения, или как базовый тип для указателей на объекты неизвестного типа.
void f() // f не возвращает значение void* pv; // указатель на объект неизвестного типа
Переменной типа void* можно присваивать указатель любого типа. На первый взгляд это может показаться не особенно полезным, поскольку void* нельзя разыменовать, но именно это ограничение и делает тип void* полезным. Главным образом, он применяется для передачи указателей функциям, которые не позволяют сделать предположение о типе объекта, и для возврата из функций нетипизированных объектов. Чтобы использовать такой объект, необходимо применить явное преобразование типа. Подобные функции обычно находятся на самом нижнем уровне системы, там, где осуществляется работа с основными аппаратными ресурсами.
Например:
void* allocate(int size); // выделить void deallocate(void*); // освободить f() { int* pi = (int*)allocate(10*sizeof(int)); char* pc = (char*)allocate(10); //... deallocate(pi); deallocate(pc); }
Указатели
Для большинства типов T T* является типом указатель на T. То есть, в переменной типа T* может храниться адрес объекта типа T. Для указателей на вектора и указателей на функции вам, к сожалению, придется пользоваться более сложной записью:
int* pi; char** cpp; // указатель на указатель на char int (*vp)[10]; // указатель на вектор из 10 int"ов int (*fp)(char, char*); // указатель на функцию // получающую параметры (char, char*) // и возвращающую int
Основная операция над указателем - разыменование, то есть ссылка на объект, на который указывает указатель. Эта операция также называется косвенным обращением. Операция разыменования - это унарное * (префиксное).
Например:
char c1 = "a"; char* p = &c1; // в p хранится адрес c1 char c2 = *p; // c2 = "a"
Переменная, на которую указывает p,- это c1, а значение, которое хранится в c1, это "a", поэтому присваиваемое c2 значение *p есть "a".
Над указателями можно осуществлять некоторые арифметические действия. Вот, например, функция, подсчитывающая число символов в строке (не считая завершающего 0):
int strlen(char* p) { int i = 0; while (*p++) i++; return i; }
Другой способ найти длину состоит в том, чтобы сначала найти конец строки, а затем вычесть адрес начала строки из адреса ее конца:
int strlen(char* p) { char* q = p; while (*q++) ; return q-p-1; }
Очень полезными могут оказаться указатели на функции; они обсуждаются в этом пункте.
1 2 3 4 5 6 7 8 9
8 8 8
| |