Другие языки программирования и технологии

Динамические двумерные массивы С++. Помогите разобраться.

Я понял что:
• Имя массива это указатель на первый байт массива - " int * a = new int [10]; ". И что a[2] эквивалентно *(a+2).
Но не могу понять как объявить двумерный массив, и зачем нужен указатель на указатель?
Эсен Алыбаев
Эсен Алыбаев
2 161
Похоже что не правильно понял

int *a;
Создать указатель на а

a = new int[500];

Так мы выделяем память для 500 элементов int
а вот "a" это как бы адрес для обращения (Совсем не так, хз как сказать)

Указатель на указатель это массив массив тоесть двумерный массив
Андрей Гуртовой
Андрей Гуртовой
24 328
Лучший ответ
Тут надо понять три вещи:
- имя массива почти всегда означает указатель на его начальный элемент (за исключением sizeof);
- квадратные скобки означают то же самое, что и прибавление к адресу;
- в C/C++ нет многомерных массивов - есть массивы указателей, массивы массивов и т. д.
А теперь:
int a[10][10];//a - указатель на начальный элемент. Этот элемент - массив из 10 int-ов.
int *a[10];//a - массив из 10 указателей, если каждому из них присвоить указатель на массив, то a можно использовать как 2-мерный массив:
for(i=0;i< 10;++i)a[ i ] = new int[10];
a[2][3]=...
int **a;//a - указатель на указатель
a = new (int *)[10];//a указывает на массив из 10 указателей
for(i=0;i< 10;++i)a[ i ] = new int[10];//все, есть та же самая структура, что и раньше:
a[2][3]=...
Валерий Егоров
Валерий Егоров
98 703
Вячеслав Бурдуков > int a[10][10];//a - указатель на начальный элемент. Этот элемент - массив из 10 int-ов.

Уточню, что a[10][10] внутри компьютера представлено также, как и a[100], т. е. при описании массива a[10][10] к элементу с индексами (2, 2) можно обратиться как a[2][2], а можно как a[0][22], или, передав адрес a указателю на int b, обратиться просто как b[22];

А обращаться к элементам одномерного массива как к элементам двумерного можно так: a[НОМЕР_СТРОКИ * ЧИСЛО_СТОЛБЦОВ_В_КАЖДОЙ_СТРОКЕ + НОМЕР_СТОЛБЦА]. Т. о. если вместо a[10][10] мы описали (или динамически распределили память на) a[100], имея в виду 10*10, то в цикле по i и j (где i - подразумеваемые строки, а j - подразумеваемые столбцы) обращаться можно a[i*10+j]. Т. о. в двумерных массивах особой нужды нет, разве что удобство программиста.
добавлю.
В реальности когда ты пишешь int a;
a есть адрес памяти, и говорят, что в ней хранятся данные размером int а может и не инт, а допусть сиксилион байт но переменная будет mytype a; Это не значит, что в а хранится, а по адресу переменной а.
Просто когда регистровые переменные
register int a; говорили, что хранится в регистре... и от того, что где-то так, где-то в памяти... замутки с пониманием.
Потому просто тупо представь, что всегда в памяти.

Там вот когда указатель
int *p=a;
То по адресу переменной p хранятся не данные, а данные для прыганья дальше по адресу, который зовется указателем.
Когда пишем потом *p значит войти в адрес переменной p и оттуда не брать фиг знает сколько байт нужного типа, а взять адрес и прыгнуть по нему и потом оттуда уже качать данные.
Еще **p вот тупой пример, мы прыгаем и прыгаем и потом берем. Еще образное представление, что звездочка это черная дыра... ты должен нырнуть в нее и только в другой вселенной уже возьмешь свои данные по адресу переменной p
Мудри как хочешь, запоминай как удобней... но в си эти указатели круто запутывают учащихся.
Вячеслав Бурдуков Да что там учащиеся! Я сам уже запутался с этими чёрными дырами. :-)
cppstudio.com/post/9555/ только вместо слово строка, подставь массив. Наверное так понятнее будет. И ссылочку скопируй и вставь в адресную строку.
Сергей Китапов
Сергей Китапов
15 388