Форум программистов, компьютерный форум CyberForum.ru

Что такое двумерный массив? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.92
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
13.08.2011, 23:24     Что такое двумерный массив? #1
Не буду долго объяснять мотивы subj-а, но не получается организовать работу с матрицей как с массивом векторов.

Пытаюсь написать цикл просмотра массива с использованием указателя на элемент в качестве счетчика.

Для вектора
C++
1
2
int b[5]={1,2,3,4,5};
for (int *i=b; i<b+5; ++i) std::cout<<*i<<' ';
Для матрицы, если считать что структура представлена вектором в котором строки последовательно сомкнуты, получается так
C++
1
2
3
4
5
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int *i=*a; i<*(a+3); i+=5)
{ for (int j=0; j<5; ++j) std::cout<<*(i+j)<<' ';
  std::cout<<std::endl;
}
это не устраивает тем, что счетчик-указатель внешнего цикла указывает на элемент матрицы (int *), а не на строки, и требуется приращение 5 (длинна строк), а не 1.

Пытаюсь написать
C++
1
2
3
4
5
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int **i=a; i<a+3; i+=1)
{ for (int *j=*i; j<*i+5; ++j) std::cout<<*j<<' ';
  std::cout<<std::endl;
}
test.cpp:57: error: cannot convert 'int (*)[5]' to 'int**' in initialization
test.cpp:57: error: comparison between distinct pointer types 'int**' and 'int (*)[5]' lacks a cast
57 строка в файле == 2 строка в примере.

Не понимаю, почему указатель совместим с вектором, а указатель-на-указатель не совместим с указатель-на-вектор?
Из этого следует сделать вывод, что n-мерный массив - это n-мерный массив, а не вектор (n-1)-мерных массивов!? Косвенно это подтверждается тем, что sizeof от матрицы пропорционален размеру матрицы, т.е. указателей на строки не создаётся.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.08.2011, 23:24     Что такое двумерный массив?
Посмотрите здесь:

C++ Что такое массив строк?
Что такое 15 - (15/4) *4 ? C++
Двумерный динамический массив, что и с чем есть? C++
Убедитесь, что двумерный массив упорядоченным по возрастанию C++
C++ что такое for(;;)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
13.08.2011, 23:52     Что такое двумерный массив? #2
C++
1
2
typedef vector<byte> Line;
vector<Line> Grid;              // -- решетка для демонстрации --
Вместо byte - любой тип
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
14.08.2011, 00:01     Что такое двумерный массив? #3
двумерный массив в памяти выглядит так:

C
1
int array[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
11 12 13 14 15 21 22 23 24 25 31 32 33 34 35

То есть реально элементы лежат последовательно, и положение элемента a[2][4] рассчитывается как адрес_начала + 2*5 + 4. Не надо его путать с массивом указателей на int, который записывается как int * array[3]; или int ** array; (обе записи равносильны).
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
14.08.2011, 00:17  [ТС]     Что такое двумерный массив? #4
Цитата Сообщение от talis Посмотреть сообщение
Не надо его путать с массивом указателей на int, который записывается как int * array[3]; или int ** array; (обе записи равносильны).
Вы книжки читали?!
"Везде" написано: "Двухмерный массив — это массив одномерных массивов."
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
14.08.2011, 00:28     Что такое двумерный массив? #5
skvor, не, ну пардон, а я о чём?
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
14.08.2011, 00:46  [ТС]     Что такое двумерный массив? #6
Двумерный массив - это не массив массивов. Многомерная таблица реализуется за счет пересчета индексов, а не за счет последовательного доступа по схеме слой-строка-элемент.
type ** эквивалентен type [][] или type *[], но компилятор считает их разными типами и не позволяет прямо присваивать.

Вобщем, тред можно закрыть, задача частично решается приведением типов
C++
1
2
3
4
for (int *i=(int *)a; i<(int *)a+3*5; i+=5)
{ for (int *j=i; j<i+5; ++j) std::cout<<*j<<' ';
   std::cout<<std::endl;
}
хотя итерация i+=5 угнетает, но думаю переделать на ++i без использования структур с явным вложением невозможно.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
14.08.2011, 00:49     Что такое двумерный массив? #7
Цитата Сообщение от skvor Посмотреть сообщение
Многомерная таблица реализуется за счет пересчета индексов
Цитата Сообщение от talis Посмотреть сообщение
положение элемента a[2][4] рассчитывается как адрес_начала + 2*5 + 4
Давайте не будем спорить о терминах.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
14.08.2011, 01:06     Что такое двумерный массив? #8
Цитата Сообщение от skvor Посмотреть сообщение
type ** эквивалентен type [][] или type *[]
type ** никогда не был эквивалентен ни type [][], ни type *[].
То, что Вы пытаетесь сделать могло бы выглядеть так:
C++
1
2
3
4
5
6
7
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int (*i)[5] = a; i < a+3; ++i)
{
    for (int j=0; j<5; ++j)
        std::cout<<*(*i+j)<<' ';
    std::cout<<std::endl;
}
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
14.08.2011, 01:44  [ТС]     Что такое двумерный массив? #9
Спасибо, вот так только надо
C++
1
2
3
4
5
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int (*i)[5]=a; i<a+3; ++i)
{ for (int *j=(int *)i; j<(int *)i+5; ++j) std::cout<<*j<<' ';
  std::cout<<std::endl;
}
собственно решался вопрос снижения затрат на пересчет индексов и последовательный доступ в многомерных массивах.

Жить стало веселей :dance3:
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
14.08.2011, 01:57     Что такое двумерный массив? #10
Тогда уж
C++
1
2
3
4
for (int (*i)[5]=a; i<a+3; ++i)
{ for (int *j= *i; j<*(i+1); ++j) std::cout<<*j<<' ';
  std::cout<<std::endl;
}
Правда я совсем не уверен, что это чем-то лучше нижеследующего кода
C++
1
2
3
4
5
int *ptr = a[0];
for (int i = 0; i < 3; ++i)
{ for (int j= 0; j < 5; ++j) std::cout<<*(ptr++)<<' ';
  std::cout<<std::endl;
}
А запросто может и хуже оказаться.
Да и вообще, индексы на x86 вычисляются довольно эффективно, а современные компиляторы зачастую хитрее "оптимизаторов". Так что обязательно надо сравнивать, в том числе и с доступом через a[i][j]
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
14.08.2011, 02:15  [ТС]     Что такое двумерный массив? #11
Да, спасибо, я постепенно прихожу к пониманию первого варианта.

Второй вариант не подходит, т.к. работает только для двумерного массива, а я хочу что б выглядело как массив массивов. Собственно, самый быстрый проход по любому массиву (но не массиву массивов) будет если поставить указатель на первый элемент и итерировать до конца циклом без вложения.
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
14.08.2011, 11:35     Что такое двумерный массив? #12
Цитата Сообщение от skvor Посмотреть сообщение
Собственно, самый быстрый проход по любому массиву (но не массиву массивов) будет если поставить указатель на первый элемент и итерировать до конца циклом без вложения.
Есть мнение, что чем проще код, тем проще его автоматически оптимизировать. Ну знаете, в кэш не попадет или предсказание ветвления подведет, или просто компилятор оставит все как есть. Так что Ваше утверждение весьма спорное. Тесты обязательно нужны.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.08.2011, 11:53     Что такое двумерный массив? #13
Цитата Сообщение от skvor Посмотреть сообщение
Что такое двумерный массив?
Размерность массива есть количество индексов, с помощью которых адресуются его элементы, то есть элементы двумерного массива адресуются двумя индексами одновременно. При этом на конкретный элемент указывает сочетание значений обоих индексов, указываемых в строгом порядке, то есть элементы a[1,2] и a[2,1] - разные. Но на сях и плюсах нет понятия многомерных массивов, поэтому с учётом того, что на тех языках, где оно есть, многомерный массив синонимичен массиву массивов равной суммарной размерности, на сях и плюсах двумерные массивы представляются только линейными массивами линейных массивов и ни как иначе.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.08.2011, 19:41     Что такое двумерный массив?
Еще ссылки по теме:

C++ Объясните что такое массив объединений и с чем его едят
Дан целочисленный двумерный массив. Известно, что среди его элементов два и только два равны между собой. Напечатать их индексы C++
C++ Что такое С++ ?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Сыроежка
Заблокирован
14.08.2011, 19:41     Что такое двумерный массив? #14
Цитата Сообщение от skvor Посмотреть сообщение
Не буду долго объяснять мотивы subj-а, но не получается организовать работу с матрицей как с массивом векторов.

Пытаюсь написать цикл просмотра массива с использованием указателя на элемент в качестве счетчика.

Для вектора
C++
1
2
int b[5]={1,2,3,4,5};
for (int *i=b; i<b+5; ++i) std::cout<<*i<<' ';
Для матрицы, если считать что структура представлена вектором в котором строки последовательно сомкнуты, получается так
C++
1
2
3
4
5
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int *i=*a; i<*(a+3); i+=5)
{ for (int j=0; j<5; ++j) std::cout<<*(i+j)<<' ';
  std::cout<<std::endl;
}
это не устраивает тем, что счетчик-указатель внешнего цикла указывает на элемент матрицы (int *), а не на строки, и требуется приращение 5 (длинна строк), а не 1.

Пытаюсь написать
C++
1
2
3
4
5
int a[3][5]={{11,12,13,14,15},{21,22,23,24,25},{31,32,33,34,35}};
for (int **i=a; i<a+3; i+=1)
{ for (int *j=*i; j<*i+5; ++j) std::cout<<*j<<' ';
  std::cout<<std::endl;
}
test.cpp:57: error: cannot convert 'int (*)[5]' to 'int**' in initialization
test.cpp:57: error: comparison between distinct pointer types 'int**' and 'int (*)[5]' lacks a cast
57 строка в файле == 2 строка в примере.

Не понимаю, почему указатель совместим с вектором, а указатель-на-указатель не совместим с указатель-на-вектор?
Из этого следует сделать вывод, что n-мерный массив - это n-мерный массив, а не вектор (n-1)-мерных массивов!? Косвенно это подтверждается тем, что sizeof от матрицы пропорционален размеру матрицы, т.е. указателей на строки не создаётся.
Я вам помогу разобраться, а то тут те, которые считают себя "экспертами по С++", вам внятно ответить не могут.

Итак, вы имеете массив a[ 3 ][ 5 ] и хотите его элементы вывести на пкечать. Фактически, вы имеете массив массивов, то есть a[ 0 ] указывает на массив из 5 элементов, a[ 1 ] указывает на следующимй массив из пяти элементов, а a[ 2 ] указывает на последний массив из пяти элементов. То есть значением a[ i ] является одномерный массив.

Когда вы испеользуете имя массива в выражениях, то он преобразуется в казатель на свой пекрвый элемент. Для вашего массива он преобразуется в указатель int ( * )[ 5 ]. Поэтому в своем внешнем цикле вы должны написать

for ( int ( *p )[ 5 ] = a; p < a + 3; ++p )

А что написать во внутреннем цикле?

Во внутренний цикл вы передаете указатель на массив, то есть int ( *p )[ 5 ]. Тогда если разыменовать этот указатель, то есть использовать выражение *p, то вы получите одномерный массив. В свою очерель если использовать имя одномерного массива в выражении, то оно преобразуется в указатель на его первый элемент.

Итак, мы имеем что выражение *p представляет собой массив вида int[ 5 ]. Если его использовать в выражениях, то он преобразуется в указатель вида int *.

Следовательно внутренний цикл должен быть записан в виде

for ( int *p1 = *p; p1 < *p + 5; ++p1 )

Как говорятфранцузу, вуаля!

Добавлено через 2 часа 37 минут
Хотел бы себя поправить, то есть заменить слово "указывать" на "представляет собой", когда я говорил об a[i] то есть a[0] представляет собой массив размерностью 5, a[1] представляет собой массив размерности 5 и т.д.
Yandex
Объявления
14.08.2011, 19:41     Что такое двумерный массив?
Ответ Создать тему

Метки
векторы, массивы, матрицы, указатели, циклы
Опции темы

Текущее время: 21:00. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru