C/C++

По вашему мнению почему первый код правильным не является?

98 073
С точки зрения стандарта алгоритмизации второе утверждение какое-то дикое. Либо программист, о котором говорится в этом утверждении немало дикий. Ведь что есть двумерный массив? Согласно теории, это одномерный массив из одномерных массивов, так? А что представляет собой одномерный массив? Это указатель на первый элемент этого массива. Следовательно, двумерный массив также является и одномерным; точнее, это одномерный массив содержащий указатели. Имя двумерного массива ссылается на начало объемлющего массива указателей, сумма имени двумерного массива и индекса даёт адрес элемента этого же массива с соответствующим индексом.
А что даёт разыменование этой суммы (запись *(m + i))? Поскольку объемлющий массив содержит адреса подмассивов, то разыменование и даёт нам адрес одного из подмассивов, что совпадает с адресом его же первого элемента. А суммирование с другим индексом даёт адрес элемента подмассива с этим индексом (*(m + i) + j). Разыменование всего выражения есть обращение к элементу подмассива объемлющего массива по адресу, разве не так? Вот так и выходит формула *(*(m + i) + j).

Ну, и что в ней не так?!? Или программист имярек имел ввиду другое? Тогда один дьявол знает, что он имел ввиду!!!
СД
Сергей Джупаров
16 172
Лучший ответ
Сергей Джупаров Не буду рассматривать первый код (но не считаю его абсолютно совершенным). А вот второй код функции print_mij выглядит небезопасным. Он будет работать правильно, если под весь двумерный массив выделен сплошной участок памяти, и, что очень важно (!!!), все подмассивы в нём занимают каждый — сплошной участок памяти, и эти подмассивы строго ранжированы по индексу в объемлющем массиве. То есть сначала идут все элементы подмассива 0, потом — все элемены подмассива 1 и т. д.
Но ведь объемлющий массив содержит указатели (!!!), а каждый из них может адресовать абсолютно любой участок памяти совершенно независимо от остальных. Таким образом сама непрерывность и строгая упорядоченность двумерного массива под угрозой, а значит, формула обращения к двумерному массиву как к СПЛОШНОМУ одномерному ...
я когда вижу КОНЬЯК МНОГОЗВЁЗДОЧНЫЙ ДИВУ ДАЮСЬ ЧТО ЛЮДЯМ СЛОЖНО ПОНЯТЬ ROW * size_col + COL для вычисления из линейного в матрицу. Удалять линейный проще delete [] array, чем городить огород потом
Legenda Krit
Legenda Krit
21 700
Legenda Krit #include iostream
void print(int(*)[3], int);
int main()
{
int table[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int rowsCount = sizeof(table) / sizeof(table[0]);
print(table, rowsCount);
return 0;
}

void print(int (*numbers)[3], int rowsCount)
{
int columnsCount = sizeof(*numbers)/ sizeof(*numbers[0]);
for(int i =0; i < rowsCount; i++)
{
for (int j = 0; j < columnsCount; j++)
std::cout << numbers[i][j] << "\t";

std::cout << std::endl;
}
}
void print(int numbers[][3], int rowsCount)
{
int columnsCount = sizeof(numbers[0])/ sizeof(numbers[0][0]);
for(int i =0; i < rowsCount; i++)
{
for (int j = 0; j < columnsCount; j++)
std::cout << numbers[i][j] << "\t";
std::cout << std::endl;
}
}
Legenda Krit я их в сети нашёл. Просто передаёшь адрес ПЕРВОГО ЭЛЕМЕНТА ПО-ЛЮБОМУ
Legenda Krit Это статический. А динамика тоже самое - передаёшь только адрес первого элемента и размерность
Sergei Talipov Идея научной подмены двумерного массива эквивалентным одномерным массивом очень даже удобна, хотя многие недооценивают это.

Но это вынуждает разработчика придерживаться строгих правил.

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