Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КРАТКИЙ ОБЗОР С.doc
Скачиваний:
1
Добавлен:
26.10.2018
Размер:
2.11 Mб
Скачать

2.3.5 Указатели

Для большинства типов T указатель на T имеет тип T*. Это значит, что переменная типа T* может хранить адрес объекта типа T. Указатели на массивы и функции, к сожалению, требуют более сложной записи:       int* pi;       char** cpp; // указатель на указатель на char       int (*vp)[10]; // указатель на массив из 10 целых       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'.       Над указателями можно выполнять и некоторые арифметические операции.       Ниже в качестве примера представлена функция, подсчитывающая число       символов в строке, заканчивающейся нулевым символом (который       не учитывается):       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;       } Широко используются указатели на функции; они особо обсуждаются в $$4.6.9

2.3.6 Массивы

Для типа T T[size] является типом "массива из size элементов типа T". Элементы индексируются от 0 до size-1. Например:       float v[3]; // массив из трех чисел с плавающей точкой:       // v[0], v[1], v[2]       int a[2][5]; // два массива, из пяти целых каждый       char* vpc; // массив из 32 символьных указателей       Можно следующим образом записать цикл, в котором печатаются целые       значения прописных букв:       extern "C" int strlen(const char*); // из <string.h>       char alpha[] = "abcdefghijklmnopqrstuvwxyz";       main()       {       int sz = strlen(alpha);       for (int i=0; i<sz; i++) {       char ch = alpha[i];       cout << '\''<< ch << '\''       << " = " <<int(ch)       << " = 0" << oct(ch)       << " = 0x" << hex(ch) << '\n';       }       } Здесь функции oct() и hex() выдают свой параметр целого типа в восьмеричном и шестнадцатеричном виде соответственно. Обе функции описаны в <iostream.h>. Для подсчета числа символов в alpha используется функция strlen() из <string.h>, но вместо нее можно было использовать размер массива alpha ($$2.4.4). Для множества символов ASCII результат будет таким:       'a' = 97 = 0141 = 0x61       'b' = 98 = 0142 = 0x62       'c' = 99 = 0143 = 0x63       ... Отметим, что не нужно указывать размер массива alpha: транслятор установит его, подсчитав число символов в строке, заданной в качестве инициализатора. Задание массива символов в виде строки инициализатора - это удобный, но к сожалению, единственный способ подобного применения строк. Присваивание строки массиву недопустимо, поскольку в языке присваивание массивам не определено, например:       char v[9];       v = "a string"; // ошибка Классы позволяют реализовать представление строк с большим набором операций (см. $$7.10).       Очевидно, что строки пригодны только для инициализации символьных массивов; для других типов приходится использовать более сложную запись. Впрочем, она может использоваться и для символьных массивов. Например:       int v1[] = { 1, 2, 3, 4 };       int v2[] = { 'a', 'b', 'c', 'd' };       char v3[] = { 1, 2, 3, 4 };       char v4[] = { 'a', 'b', 'c', 'd' }; Здесь v3 и v4 - массивы из четырех (а не пяти) символов; v4 не оканчивается нулевым символом, как того требуют соглашение о строках и большинство библиотечных функций. Используя такой массив char мы сами готовим почву для будущих ошибок.       Многомерные массивы представлены как массивы массивов. Однако нельзя при задании граничных значений индексов использовать, как это делается в некоторых языках, запятую. Запятая - это особая операция для перечисления выражений (см. $$3.2.2). Можно попробовать задать такое описание:       int bad[5,2]; // ошибка или такое       int v[5][2];       int bad = v[4,1]; // ошибка       int good = v[4][1]; // правильно Ниже описывается массив из двух элементов, каждый из которых является, в свою очередь, массивом из 5 элементов типа char:       char v[2][5]; В следующем примере первый массив инициализируется пятью первыми буквами алфавита, а второй - пятью младшими цифрами.       char v[2][5] = {       { 'a', 'b', 'c', 'd', 'e' },       { '0', '1', '2', '3', '4' }       };       main() {       for (int i = 0; i<2; i++) {       for (int j = 0; j<5; j++)       cout << "v[" << i << "][" << j       << "]=" << v[i][j] << " ";       cout << '\n';       }       }       В результате получим:       v[0][0]=a v[0][1]=b v[0][2]=c v[0][3]=d v[0][4]=e       v[1][0]=0 v[1][1]=1 v[1][2]=2 v[1][3]=3 v[1][4]=4