Учитывая, что размерности известны, т.к. массив статический:
void aa( int _a[][10] )
{
ShowMessage( _a[2][9] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int a[12][10];
a[2][9]= 29;
aa( a );
}
Но Вам же нужно передавать размеры в виде параметров. Тогда встаёт
вопрос: Зачем, создавая статический массив int a[12][12], передавать
его размеры, как будто он динамический?
ИМХО: размеры массива, приведённые Вами, приведены лишь для примера,
тогда совет: В следующий раз обозначайте к примеру так: a[m][n].
Будет понятнее, что размеры не статические.
Будем считать, что именно так Вы и написали, тогда:
void aa( int **_a, int _m, int _n )
{
ShowMessage( _a[2][9] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int **a;
int m= 12;
int n= 10;
a= new int*[m];
a[2]= new int[n];
a[2][9]= 29;
aa( a, m, n );
}
Если же всё-таки у Вас имеются всё-таки статические массивы, но
несколько и разных размерностей, к примеру: int a[12][10], b[10][12], то:
void aa( int *_a, int _m, int _n )
{
int **a;
a= new int*[_m];
for( int f= 0; f< _m; f++ )
a[f]= _a +f*_n;
ShowMessage( a[_m -1][_n -1] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int a[12][10];
int b[10][12];
a[11][9]= 119;
b[9][11]= 911;
aa( a[0], 12, 10 );
aa( b[0], 10, 12 );
}
И, наверное, крайний случай. Если же всё-таки у Вас имеются всё-таки статические
массивы и все одного размера, но разных типов, к примеру: int
a[12][10], double b[10][12], то:
template <class A> void aa( A _a[][10] )
{
ShowMessage( _a[2][9] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int a[12][10];
double b[12][10];
a[2][9]= 29;
b[2][9]= 29.29;
aa( a );
aa( b );
}
И т.д. и т.п. и прочее.
Коментарии к коду нужны?
Вопросы?
Ваша программа работает корректно? Один звонок и я всё исправлю!
Делаю потенциальные фичи :))
Re[3]: Передача указателя на двумерный массив в функцию
Большое спасибо, за исчерпывающий ответ. Комментарии — излишни.
Только один вопрос — в приведенном вами коде
Б>Учитывая, что размерности известны, т.к. массив статический: Б>
Б>void aa( int _a[][10] )
Б>{
Б> ShowMessage( _a[2][9] );
Б>}
Б>void __fastcall TForm2::Button2Click(TObject *Sender)
Б>{
Б> int a[12][10];
Б> a[2][9]= 29;
Б> aa( a );
Б>}
Б>
Первая строка должна быть void aa( int _a[12][10] )? или оставить скобки пустыми как у Вас,
и второй вопрос при передаче массива таким образом происходит копирование или все таки — передача указателя?
Спасибо за ответ.
Alexander N. Treyner
Re[4]: Передача указателя на двумерный массив в функцию
Здравствуйте, sndralex, Вы писали:
S>Здравствуйте, Багер, Вы писали:
S>Первая строка должна быть void aa( int _a[12][10] )? или оставить скобки пустыми как у Вас,
Не принципиально, т.к. компилятору нужно знать только через сколько данных пойдёт следующая размерность.
Как справедливо заметили выше, запись int a[144] в памяти выглядит точно так же, как и int a[12][12]. Вот с трёхмерными массивами, у меня на экзамене были проблемы. Он, по словам препода, не эквивалентен записи int a[1728], как-то по-другому. Сейчас с ходу тоже не скажу. S>и второй вопрос при передаче массива таким образом происходит копирование или все таки — передача указателя?
Проведя несложные добавления к коду:
void aa( int _a[][10] )
{
_a[2][9]= 292;
ShowMessage( _a[2][9] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int a[12][10];
a[2][9]= 29;
aa( a );
ShowMessage( a[2][9] );
}
Мы убеждаемся, что указатель передаётся только указателем, а не целый массив тащит за собой. Собственно, на то он и указатель ))
Ваша программа работает корректно? Один звонок и я всё исправлю!
Делаю потенциальные фичи :))
Re: Передача указателя на двумерный массив в функцию
S>И что-то я потерялся с передачей массива в качестве параметра. S>Помогите, люди добрые(только сильно не пинайте.)
А если так:
template<class Array>
void F(Array array, int i, int j)
{
array[1][1] = 20;
}
void main()
{
int a[10][10];
F(a, 10, 10);
cout << a[1][1];
}
Плюсы
Не нужно заранее указывать размер
Доступ идет чере два индекса, т.е. не нужен различный перевод
Re: Передача указателя на двумерный массив в функцию
От:
Аноним
Дата:
09.12.02 13:57
Оценка:
void fun(int (*pArra)[10]){
pArra[0][0] = 10;
}
Re[3]: Передача указателя на двумерный массив в функцию
От:
Аноним
Дата:
09.12.02 14:00
Оценка:
C ума сошел? Не вздумай так писать! Это глупейшая ошибка! int **p и int a[10][10] — совершенно разные вещи. Имя такого массива — это не указатель на целое, а указатель на массив (одномерный), можно либо
void fun(int (*pArray)[10]);
либо
void fun(int * pArray)//тут тебе придется работать уже как с одномерным
//а передавать в нее так fun(*a) или fun(&a[0][0]) или fun(a[0]).
Re[2]: Передача указателя на двумерный массив в функцию
Здравствуйте, Багер, Вы писали:
Б>Коментарии к коду нужны?
Нужны. Во-первых спасибо за примеры. Во-вторых, если не затруднит — позволь задать несколько вопросов.
Б>Учитывая, что размерности известны, т.к. массив статический: Б>
Б>void aa( int _a[][10] )
Б>{
Б> ShowMessage( _a[2][9] );
Б>}
Б>void __fastcall TForm2::Button2Click(TObject *Sender)
Б>{
Б> int a[12][10];
Б> a[2][9]= 29;
Б> aa( a );
Б>}
Б>
Если я говорю:
int a[12][10];
, то a это что ? Указатель ? Или указатель на указатель ?
И почему в объявлении функции aa первая размерность массива не важна, в то время как вторая размерность имеет значение ?
Второй и третий пример, мне честно говоря повторить не удалось —
Во втором примере при вызове функции — "Инструкция обратилась к памяти.... ..не может быть read..". В чем дело ?
В третьем печатает, но не те символы. Как я понимаю, проблема с выходом за границы массива ?
Вот пример в котором я пытался все это повторить:
#include <stdio.h>
void aa(int _a[][10])
{
printf("%d\n",_a[2][9]);
}
void bb(int **_b, int _m, int _n)
{
printf("%d\n",_b[_m][_n]);
}
void cc(int *_a, int _m, int _n)
{
int **a;
a = new int*[_m];
for (int f=0; f<_m; f++)
a[f] = _a + f*_n;
printf("%d\n",a[_m-1][_n-1]);
}
void main()
{
// Первый случай - размерности известны и массив статическийint a[12][10];
a[2][9] = 29;
aa(a);
// Комментарий - в функции aa можно было написать и так - (int _a[12][10])
// и даже так _a[10][10].
// Пример второй - массив динамическийint **b;
int m = 12;
int n = 10;
b = new int*[m];
b[2] = new int[n];
b[2][9] = 29;
bb(b,m,n); // здесь вылетает
// Пример третий - все таки статические массивы,
// но несколько и разных размерностейint c[12][10];
int d[10][12];
c[11][9] = 119;
c[9][11] = 911;
cc(c[0], 12, 10); // а здесь печатает не те значения
cc(d[0], 10, 12); // а здесь печатает не те значения
}
... << RSDN@Home 1.0 beta 2 >>
Re[4]: Передача указателя на двумерный массив в функцию
Здравствуйте
>Это монолог. Ты посмотрел, что я написал про многомерные массивы? А то говоришь, на экзамене не сообразил
Да, конечно. И крайне озабочен этим фактом, т.к. никто из тех, кому
был задан этот же вопрос так же — ответили неправильно!
Однако, может меня и память подводит, может массив был динамически
построенный? В этом случае надо брать указатель на следующую
размерность. Задача, в принципе, усложняется, но не настолько, чтобы
не решать её!
{
int *****a;
a[2][4][6][3][7]= 24637;
aa( a ); //исправно
}
Может задача была на неизвестно какого построения массив был принят
функцией, вот здесь уже возникнут проблемы.
Статический массив же не создаёт указатели на начало следующей
размерности. Во всяком случае такой код не работает:
{
int b[5][6][7][8][9];
b[2][4][6][3][7]= 24637;
aa( (int*****)b ); //так неверно
aa( (int*****)&b ); //и так тоже неверно
}
Связано это с тем, что статические массивы создаются как
одномерные. Вот эта задача, наверное, и была предложена нам на
экзамене: Обобщённый одной функцией приём статического и динамического
массива. Требуется вычислить значение его ячеек. Размерности известны.
Шаблонный вариант, предложенный Денвером, решает эту задачу, но тогда,
шаблоны для нас были чем-то из ряда вон выходящим )) Денвер рулит!
И так, вернёмся к примерам:
>Если я говорю: int a[12][10]; >то a это что ? Указатель ? Или указатель на указатель ?
Указатель на десять интов. Тип: int (*)[10] >И почему в объявлении функции aa первая размерность массива не важна, >в то время как вторая размерность имеет значение ?
Потому, что иначе для операции _а++ неизвестно на какой объём данных
указывает _а, чтобы была возможность инкрементировать его до
следующего объёма. А для операции _а[n]++ известно — размер инта, а
кол-во десятиинтовых последовательностей нигде компилятором не
используется, значит и не обязательно для конкретизации. >aa( a );
В этом примере — передача указателя на первую десятиинтовую
последовательность.
По поводу второго примера. Обратите внимание, что я выделил память
только для того, чтобы суметь задать значение а[2][9]. Соответственно,
это значение в Вашей функции bb и надо выводить, а Вы выводите: >printf("%d\n",_b[_m][_n]);
Границы размеров массива, которые вообще не входят в состав данных
массива.
Надо
printf("%d\n",_b[2][9]);
void aa( int **_a, int _m, int _n )
{
ShowMessage( _a[2][9] );
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int **a;
int m= 12;
int n= 10;
a= new int*[m]; //Инициализация указателя на массив указателей
a[2]= new int[n]; //Инициализация указателя[2] на массив
a[2][9]= 29;
aa( a, m, n ); // Передаём указатель на массив указателей
}
Третий пример тоже с ошибкой: >c[9][11] = 911;
Должно быть >d[9][11] = 911;
т.к. у "с" одиннадцатого элемента в размерности нет.
void aa( int *_a, int _m, int _n )
{
int **a;
a= new int*[_m]; //Инициализация указателя на массив указателей
for( int f= 0; f< _m; f++ ) //Перебор всей первой размерности
a[f]= _a +f*_n; /*Расчёт адресов нулевых элементов второй
размерности от первого элемента статической последовательности
интов и инициализация этими адресами соответствующих указателей
массива указателей*/
ShowMessage( a[_m -1][_n -1] ); //Чтение пограничных значений
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int a[12][10];
int b[10][12];
a[11][9]= 119; // Инициализация пограничных элементов
b[9][11]= 911; // для проверки корректности работы
aa( a[0], 12, 10 ); //Конвертация указателя на несколько интов
aa( b[0], 10, 12 ); //в одномерный массив по одному инту
}
Пример 4 не актуален из-за более качественного примера Денвера.
Не люблю писать комментарии! Ой, не люблю! ))
Ваша программа работает корректно? Один звонок и я всё исправлю!
Делаю потенциальные фичи :))
Re[5]: Передача указателя на двумерный массив в функцию
Здравствуйте, Багер, Вы писали:
Б>Здравствуйте
>>Если я говорю: int a[12][10]; >>то a это что ? Указатель ? Или указатель на указатель ?
Б>Указатель на десять интов. Тип: int (*)[10]
Не понял. Почему ?
Я рассуждаю так —
если объявлено a[12] — то это указатель на 12 int-ов
cоответственно если объявлено так a[12][10] — то a это указатель на
12-дцать 10-ти int-х последовательностей. Или, что тоже самое —
указатель на (10*12)=120 int-ов.
Почему же на 10 интов. Не понимаю. Если не сложно — поясни ?
>>И почему в объявлении функции aa первая размерность массива не важна, >>в то время как вторая размерность имеет значение ?
Б>Потому, что иначе для операции _а++ неизвестно на какой объём данных Б>указывает _а, чтобы была возможность инкрементировать его до Б>следующего объёма. А для операции _а[n]++ известно — размер инта,
Размер инта ? Блин, я считал, что размер 10-ти интовой последовательности.
Почему не так ?
Б>кол-во десятиинтовых последовательностей нигде компилятором не Б>используется, значит и не обязательно для конкретизации.
Это я понял. Спасибо.
Б> ...Третий пример тоже с ошибкой..
Согласен. Обыкновенная невнимательность.
... << RSDN@Home 1.0 beta 2 >>
Re[6]: Передача указателя на двумерный массив в функцию
Здравствуйте DemAS
>>>Если я говорю: int a[12][10]; >>>то a это что ? Указатель ? Или указатель на указатель ? Б>>Указатель на десять интов. Тип: int (*)[10] RFcD>Не понял. Почему ?
Вопрос по стандарту. Логику предпосылок именно такой, а не какой-либо иной
организации статических массивов можно объяснить только экономией
памяти на указателях, которые, фактически, и не требуются, т.к. весь
массив хранится одной линейкой в памяти. Динамический массив —
хранится кусками. От того и разница.
RFcD>Я рассуждаю так — если объявлено a[12] — то это указатель на 12 int-ов
В корне неверно.
Во-первых: a[12] — это всё-таки только массив
Во-вторых: а — действительно является указателем на начало массива
типов инт, НЕ 12-инт(!), т.к. 12 — это только объём отведённой памяти,
но никак не связанный с работой указателя. а++ приведёт Вас на элемент
массива [1], а не на а[12].
А вот для следующего RFcD>cоответственно если объявлено так a[12][10] — то a это указатель на RFcD>12-дцать 10-ти int-х последовательностей. Или, что тоже самое - RFcD>указатель на (10*12)=120 int-ов.
Нет! Я же привёл тип "а" — "int (*)[10]", читайте внимательнее. Это указатель
на десять интов, т.к. "10" — это именно то количество интов, которое
будет пропущено при операции а++ от самого первого элемента массива.
а[1] — это опять же указатель. Из чего можно сделать вывод, что
объяснение "на пальцах" больше путает, чем разъясняет. К сожалению, не
могу привести толковую книжку, т.к. уже не помню в какой именно
толково освещали именно этот момент. Но именно из-за того, что
потенциальные программисты не могут разобраться с указателями, многие
и меняют направление своего обучения, но я отвлёкся.
Т.е. а[1] всё-таки является указателем, но это псевдо-указатель. Он
рассчитывается компилятором, т.к. явная ссылка на 10 интов в записи
а[1] не присутствует. Компилятор это преображает в вид: а+1, т.е. к
началу массива прибавляется десять размерностей инта. Из этого, запись
а[1] и становится как бы указателем. Т.е. для неё работает операция
++, которая передвигает указатель на один инт, т.к. это последняя
размерность массива, т.е. указатель эквивалентен пониманию записи
int *аа, где аа = а[1]. RFcD> Почему же на 10 интов. Не понимаю. Если не сложно — поясни ?
Потому что память статического массива линейна. Сначала идут данные
последней размерности для всех остальных размерностей равных 0. Затем
идут данные последней размерности для предпоследней размерности равной
1, пред-предпоследней и остальных равных 0. Затем данные последней
размерности для предпоследней равной 2, пред-прелпоследней равной 0.
Затем идут данные последней размерности для предпоследней равной 0,
пред-предпоследней равной 1, всех остальных равных 0. И т.д. Место для
указателей не выделяется, ибо элементарно на стадии компиляции
рассчитывается.
>>>И почему в объявлении функции aa первая размерность массива не важна, >>>в то время как вторая размерность имеет значение ?
Б>>Потому, что иначе для операции _а++ неизвестно на какой объём данных Б>>указывает _а, чтобы была возможность инкрементировать его до Б>>следующего объёма. А для операции _а[n]++ известно — размер инта,
RFcD> Размер инта ? Блин, я считал, что размер 10-ти интовой последовательности. RFcD> Почему не так ?
Читайте выше.
И разбирайтесь. Затем выложите сюда содержание в памяти трёхмерного
массива данных а[2][4][6], где данные равны по индексу: сотни — первый
индекс, десятки — второй, единицы — третий.
Ваша программа работает корректно? Один звонок и я всё исправлю!
Делаю потенциальные фичи :))
Re[2]: Передача указателя на двумерный массив в функцию
От:
Аноним
Дата:
09.09.07 13:39
Оценка:
Люди а подскажите кто нить как написать фукнцию в который передается указатель на двумерный массив и в ней выделяется память под этот массив просто воэ тот вариант не работает
int **Mas = NULL; // объявлен как лопкальный
int StolbCount = 10;
int StrokCount = 10;
void SetMas(int **Mas, int StolbCount, int StrokCount)
{
Mas = new int*[StolbCount];
for (int i = 0; i < StolbCount; i++)
{
Mas[i] = new int[StrokCount];
}
}
после этого если я с этим массивом что нить делаю вылетает ошибка
Re[3]: Передача указателя на двумерный массив в функцию
Здравствуйте, Аноним, Вы писали:
А>Люди а подскажите кто нить как написать фукнцию в который передается указатель на двумерный массив и в ней выделяется память под этот массив просто воэ тот вариант не работает
int StolbCount = 10;
int StrokCount = 10;
int **Mas = NewMas( StolbCount, StrokCount ); // объявлен как лопкальныйint ** NewMas(int StolbCount, int StrokCount)
{
int **Mas = new int*[StolbCount];
for (int i = 0; i < StolbCount; i++)
{
Mas[i] = new int[StrokCount];
}
return Mas;
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Передача указателя на двумерный массив в функцию
От:
Аноним
Дата:
09.09.07 15:26
Оценка:
Нефига се ... Большое спасибо
Re: Передача указателя на двумерный массив в функцию