Массивы и указатели

Автор работы: Пользователь скрыл имя, 20 Марта 2011 в 00:49, лекция

Описание работы

Между массивами и указателями существует очень тесная связь, поэтому обычно их рассматривают вместе. Но, прежде чем исследовать эту связь, давайте проверим наши знания о массивах и пополним их, а уж после этого перейдем к изучению связи между массивами и указателями.

Содержание работы

Массивы
Инициализация массивов и классы памяти
Указатели массивов
Функции, массивы и указатели
Использование указателей при работе с массивами
Операции с указателями
Многомерные массивы
Инициализация двумерного массива
Указатели и многомерные массивы
Функции и многомерные массивы

Файлы: 1 файл

13_Массивы и указатели.doc

— 183.50 Кб (Скачать файл)

    Сначала запоминается первая строка, за ней вторая, затем третья и т. д. Таким образом, в нашем примере: 

    pri == &zippo[0][0] /* 1-я строка, 1 столбец */

    pri + 1 == &zippo[0][1] /* 1-я строка, 2 столбец */

    pri + 2 == &zippo[1][0] /* 2-я строка, 1 столбец */

    pri + 3 == &zippo[1][1] /* 2-я строка, 2 столбец */ 

    Получилось? Хорошо, а на что указывает pri + 5? Правильно, на 

    zippo[2][1]. 

    Мы  описали двумерный массив как  массив массивов. Если zippo является именем нашего двумерного массива, то каковы имена четырех строк, каждая из которых является массивом из двух элементов? Имя первой строки zippo [0], имя четвертой строки zippo [3]; вы можете заполнить пропущенные имена. Однако имя массива является также указателем на этот массив в том смысле, что оно ссылается на первый его элемент. Значит,

    zippo[0] == &zippo[0][0]

    zippo[1] == &zippo[1][0]

    zippo[2] == &zippo[2][0]

    zippo[3] == &zippo[3][0] 

    Это свойство является более, чем новшеством. Оно позволяет использовать функцию, предназначенную для одномерного  массива, для работы с двумерным  массивом! Вот доказательство (хотя мы надеемся, что теперь вы бы поверили нам и так) использования двумерного массива в нашей программе нахождения среднего значения: 

/* одномерная  функция, двумерный массив */

main ()

{

static int junk [3] [4] = {

                                    {2, 4, 6, 8},

                                    {100, 200, 300, 400},

                                    {10, 40, 60, 90}

                              }; 

int row;

for (row = 0; row < 3; row++ )

printf(" Среднее  строки %d равно %d.\n",

      row, mean(junk[row], 4) ); /* junk [row] — одномерный  массив из четырех элементов  */

} 

/* находит  среднее в одномерном массиве */

int mean(array,n)

int array[], n;

{

int index; long sum;

if (n > 0)

      {

      for (index = 0, sum = 0; index < n; index++)

            sum += (long) array [index];

      return( (int) (sum/n) );

      }

else

      {

      printf("Heт  массива\n");

      return(0);

      }

} 

    Результат работы программы: 

    Среднее строки 0 равно 5.

    Среднее строки 1 равно 250.

    Среднее строки 2 равно 50. 

      1. Функции и многомерные  массивы

    Предположим, что вы хотите иметь функцию, работающую с двумерным массивом, причем со всем целиком, а не с частями. Как вы запишите определения функции и ее описания? Подойдем к этому более конкретно и скажем, что нам нужна функция, управляющая массивом junk[][] в нашем последнем примере. Пусть функция main () выглядит так: 

/* junk в main */

main ()

{

static int junk[3][4] = {

                                    {2, 4, 5, 8},

                                    {100, 200, 300, 400},

                                    {10, 40, 60, 90}

                              };

stuff(junk);

} 

    Функция stuff () использует в качестве аргумента junk, являющийся указателем на весь массив. Как написать заголовок функции, не зная, что делает stuff ()?

    Попробуем написать: 

    stuff (junk)

    int junk[];? 

    или 

    stuff(junk)

    int junk[][];? 

    Нет и нет. Первые два оператора еще  будут работать некоторым образом, но они рассматривают junk как одномерный массив, состоящий из 12 элементов. Информация о расчленении массива на строки отсутствует.

    Вторая  попытка ошибочна, потому что хотя оператор и указывает, что junk является двумерным массивом, но нигде не говорится, из чего он состоит. Из шести строк и двух столбцов? Из двух строк и шести столбцов? Или из чего-нибудь еще? Компилятору недостаточно этой информации. Ее дают следующие операторы: 

    stuff(junk)

    int junk[][4]; 

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

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

    char *list[]; 

    Символьные  строки представляют одно из наиболее частых применений массивов и указателей; мы вернемся к этой теме позднее.

    Что вы должны были узнать

  • Как объявить одномерный массив: long id_ no [200];
  • Как объявить двумерный массив: short chess[8] [8];
  • Какие массивы можно инициализировать: внешние и статические.
  • Как инициализировать массив: static int hats[3] = {10,20,15};
  • Другой способ инициализации: static int caps[] = {3,56,2};
  • Как получить адрес переменной: использовать операцию &
  • Как получить значение, ссылаясь на указатель: использовать операцию *
  • Смысл имени массива: hats == &hats[0]
  • Соответствие массива и указателя: если ptr = hats; то ptr + 2 == &hat[2]; и *(ptr + 2) == hat[2];
  • Пять операций, которые можно применять для переменных типа указатель: см. текст.
  • Метод указателей для функций, работающих с массивами.

    Вопросы и ответы

    Вопросы

  1. Что напечатается в результате работы этой программы?

#define PC(X, Y) printf("%c %c\n", X, Y)

char ref[] = { D, О, L, Т};

main ()

{

char *ptr;

int index;

for (index = 0; ptr = ref; index < 4; index++, ptr++ )

      PC(ref[index], *ptr);

}

  1. Почему в вопросе 1 массив ref описан до оператора main ()?
  2. Определите значение *ptr и *(ptr + 2) в каждом случае:

      int *ptr;

      static int boop[4] = {12, 21, 121, 212};

      ptr = boop;

    1. float *ptr;

      static float awk[2][2] = { { 1.0, 2.0}, {3.0, 4.0}};

      ptr = awk[0];

    1. int *ptr;

      static int jirb[4] = {10023, 7};

      ptr = jirb;

    1. int = *ptr;

      static int torf[2][2) = {12, 14, 16};

      ptr = torf[0];

    1. int *ptr;

      static int fort[2][2] = {{ 12}, {14, 16}};

      ptr = fort[0];

  1. Предположим, у нас есть описание static int grid[30][100];
    1. Выразите адрес grid [22] [56] иначе.
    2. Выразите адрес grid[22] [0] двумя способами.
    3. Выразите адрес grid[0][0] тремя способами.

    Ответы

    

D D

    

О О

    

L L

    

Т Т

  1. По умолчанию такое положение ref относит его к классу памяти типа extern, a массивы этого класса памяти можно инициализировать.
    1. 12 и 121
    1. 1.0 и 3.0
    2. 10023 и 0 (автоматическая инициализация нулем)
    3. 12 и 16
    4. 12 и 14 (именно 12 появляется в первой строке из-за скобок).
    1. &grid[22][56]
    2. &grid[22][0] и grid[22]
    3. &grid[][] и grld[0] и grid

    

Упражнение

  1. Модифицируйте нашу метеорологическую программу таким образом, чтобы она выполняла вычисления, используя указатели вместо индексов. (Вы по-прежнему должны объявить и инициализировать массив.)

Информация о работе Массивы и указатели