Почему я не могу передать двумерный массив как указатель на указатель, но могу передать одномерный массив как указатель - PullRequest
0 голосов
/ 23 ноября 2018

Возможно, этот код работает

void printD(int * ar,int r)
    {
        for(int i = 0; i < r; i++)
            cout<<ar[i]<<endl;
    }
int main()
{
    int ar[3] = {1,2,3};
    printD(ar,3);
    return 0;
}

Но этот код не работает

void print2D(int ** ar,int r,int c)
    {
        for( int i = 0; i< r;i++)
            for(int j = 0; j < c;j++)
            cout<<ar[i][j]<<endl;
    }
int main()
{

   int ar2[1][2] = {{3,1}};
   print2D(ar2,1,2);
    return 0;
}

Я не понимаю, почему это не работает?

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Проблема заключается в том, как рассчитываются адреса памяти.a[0] является первым элементом, а a[1] - вторым элементом, поэтому адрес a[1] - это позиция a[0] плюс размер элемента.Здесь нет проблем, адрес любого элемента может быть рассчитан с умножением позиции первого элемента на величину смещения, умноженную на размер элемента.

Как это работает с многомерными массивами?Каково расстояние между a[0][5] и a[1][5]?Ну, это зависит от размера строки (я использую эту терминологию для примера, в действительности нет никаких «строк»), так как в итоге это всего лишь один блок памяти.Если в строке 10 элементов, то расстояние в 10 раз превышает размер элемента.Таким образом, этот размер строки важен, без него невозможно точно определить местоположение элементов в массиве.Теперь с этим здесь:

void print2D(int ** ar,int r,int c)

Как он мог знать, что размер строки?ar[1][0] - это первый элемент второй строки, поэтому, если строка имеет размер 10, то это будет 10-й элемент в блоке памяти.Однако, если размер строки равен 20, то это будет 20-й элемент, и это будет другой адрес.Так как бы он узнал?

Код не работает, потому что для вычисления адресов ему потребовалась бы информация, но он не имеет этой информации.

0 голосов
/ 23 ноября 2018

2-мерный массив неявно преобразуется в указатель на одномерный массив, а не в указатель на указатель.

void print2D(int (*ar)[2],int r,int c)
{
     //  definition omitted for brevity
}
int main()
{

   int ar2[1][2] = {{3,1}};
   print2D(ar2,1,2);
   return 0;
}

Также нет преобразования из указателя в массив (как вПриведенный выше пример) в указатель на указатель.

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

0 голосов
/ 23 ноября 2018

Этот массив int ar2[1][2] фактически распадается до int(*)[2].

Нет промежуточного указателя на указатель, который будет выделен, существует непрерывный одномерный массив, к которому можно получить доступ в 2D, отсюда и остальные [2], который дает возможность перейти от одного ряда к другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...