Присвоить указатель указателем на многомерный массив в функции

void print_first_n_row(double **matrix, int n, int row_size) {
 double (*abc)[row_size];
 abc=matrix;}

У меня возникает ошибка назначения из несовместимого типа указателя [-Winсовместимые-типы-указателей] abc=matrix. Как я могу это решить?


person ajdfhjkshg    schedule 06.05.2020    source источник
comment
Изменив void print_first_n_row(double **matrix, int n, int row_size) на void print_first_n_row(int n, int row_size, double (*matrix)[row_size]) и соответствующим образом изменив вызывающий? (Это зависит от того, как используются функция и abc)   -  person MikeCAT    schedule 06.05.2020
comment
Я не понимаю, почему какой-либо орган проголосовал бы за закрытие этого. Это вопрос, который содержит часто встречающиеся загадки для любого нового программиста на C, поэтому он будет интересен другим начинающим программистам.   -  person ryyker    schedule 06.05.2020
comment
Вам нужно показать нам код, который вызывает print_first_n_row, и как был объявлен параметр, соответствующий matrix.   -  person John Bode    schedule 06.05.2020


Ответы (4)


Матрица — это абстрактный тип данных. То, как вы это реализуете, является деталью реализации.

В этом ответе я подробно описал, как реализовать такой тип в C.

Многомерные массивы на самом деле не существуют в C. В C есть только массивы массивов или массивы указателей или другие типы, включая массивы скаляров. Проверьте, прочитав n1570 (стандарт C11 ).

У меня возникает ошибка назначения из несовместимого типа указателя [-Winсовместимые-типы-указателей] abc=matrix. Как я могу это решить?

Либо думайте в терминах абстрактных типов данных, либо читайте больше о C динамическом выделении памяти (рассмотрите возможность использования элементы гибкого массива) и о Язык программирования C.

Вы найдете много примеров исходного кода, связанного с матрицами, на github или gitlab и в других местах.

person Basile Starynkevitch    schedule 06.05.2020

Примечание. Этот ответ относится только к сообщению об ошибке, а не к логике передачи указателей на матрицу.


"У меня возникает ошибка присваивания из несовместимого типа указателя [-Wincompile-pointer-types] abc=matrix. Как мне решить эту проблему?"

double (*abc)[row_size]; - abc является указателем на массив double.

double **matrix - matrix является указателем на указатель на double.

Есть несоответствие. * против **.

Вы не можете присвоить значение указателя указателю на double указателю на массив double.

Измените double (*abc)[row_size]; на double **abc или double (**abc)[row_size]; или просто используйте matrix, если в противном случае abc не требуется.

person RobertS supports Monica Cellio    schedule 06.05.2020

Что ж, ответ заключается в том, что matrix и abc должны быть объявлены одинаково. Либо вам нужно изменить прототип на

void print_first_n_row(int n, int row_size, double (*matrix)[row_size]) // row_size needs to be defined first
{
  double (*abc)[row_size] = matrix;
  ...
}

или вам нужно изменить определение abc на

double **abc;

Это зависит от того, как вы вызываете определение параметра matrix и как вы вызываете print_first_n_row.

Предполагая, что ваш код выглядит примерно так:

int main( void )
{
  int rows = ...;  // assumes rows and cols are set at runtime
  int cols = ...;
  ...
  double matrix[rows][cols];
  ...
  print_first_n_rows( matrix, n, cols )
  ...
}

тогда первое решение правильное, и вам нужно изменить вызов на

  print_first_n_rows( n, cols, matrix );
person John Bode    schedule 06.05.2020

В других ответах было подробно объяснено, что попытка выполнять назначения с использованием несовместимых типов неверна. Даже если компилятор не предупредил вас, эти присваивания часто могут привести к неопределенному поведению. Но в C многомерные массивы хранятся в отдельных смежных блоках памяти_, например:

in array[4][2] = {{1,2,3,4},{5,6,7,8}};

Хранится в памяти как единый последовательный блок локаций:

|1|2|3|4|5|6|7|8|

Не, как вы можете себе представить, в нескольких блоках:

|1|2|3|4|
|5|6|7|8|

Таким образом, можно создать единую переменную-указатель, которая может быть установлена ​​как указывать на любое место в массиве C (того же базового типа) и может использоваться, например, для присвоения значений этому массиву. , как показано в следующей адаптации с использованием массива переменной длины:

int main(void)
{
    print_first_n_row(4,2);// params to create 4X2 array

    return 0;
}

void print_first_n_row(int r, int c) 
{
    double matrix[r][c];        //create array using Variable Length Array
    double *abc = &matrix[0][0];//create pointer of same base type
                                //and set address to pointer to point to 
                                //first location of matrix
    printf("%s", "array contents:");
    for(int i=0; i<r*c; i++)
    {
        *(abc + i) = i*i;
        printf("%0.2f,", *(abc + i));

    }
}  

Или, в соответствии с вашим примером передачи массива в качестве аргумента, пока типы одинаковы, возможность использования указателя для индексации местоположений массива также сохраняется:

Передача аргумента массива:

void print_first_n_row(double matrix[4][2]);

int main(void)
{
    double array1[4][2] = {1,2,3,4,5,6,7,8};
    print_first_n_row(array1);

    return 0;
}

void print_first_n_row(double matrix[4][2]) 
{
    double *abc = &matrix[0][0];//create pointer of same base type
                                //and set address to pointer to point to 
                                //first location of matrix
    ...(same as first example)
person ryyker    schedule 06.05.2020