Опубликован: 10.10.2006 | Доступ: свободный | Студентов: 6020 / 456 | Оценка: 4.26 / 3.88 | Длительность: 31:30:00
Лекция 2:

Описания и константы

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;
}

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;    // указатель на char

Можно следующим образом записать цикл, в котором печатаются целые значения прописных букв:

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. Для множества символов ASCII результат будет таким:

'a' = 97 = 0141 = 0x61
'b' = 98 = 0142 = 0x62
'c' = 99 = 0143 = 0x63
...

Отметим, что не нужно указывать размер массива alpha: транслятор установит его, подсчитав число символов в строке, заданной в качестве инициализатора. Задание массива символов в виде строки инициализатора - это удобный, но к сожалению, единственный способ подобного применения строк. Присваивание строки массиву недопустимо, поскольку в языке присваивание массивам не определено, например:

char v[9];
v = "a string";          // ошибка

Классы позволяют реализовать представление строк с большим набором операций.

Очевидно, что строки пригодны только для инициализации символьных массивов; для других типов приходится использовать более сложную запись. Впрочем, она может использоваться и для символьных массивов. Например:

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 мы сами готовим почву для будущих ошибок.

Многомерные массивы представлены как массивы массивов. Однако нельзя при задании граничных значений индексов использовать, как это делается в некоторых языках, запятую. Запятая - это особая операция для перечисления выражений. Можно попробовать задать такое описание:

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
Дарья Федотова
Дарья Федотова
Сергей Березовский
Сергей Березовский

В рамках проф. переподготовки по программе "Программирование"

Есть курсы, которые я уже прошел. Но войдя в курс я вижу, что они не зачтены (Язык Ассемблера и архитектура ЭВМ, Программирование на С++ для профессионалов). Это как?

Роман Островский
Роман Островский
Украина
Оксана Пагина
Оксана Пагина
Россия, Москва