Jump to content

    
Sign in to follow this  
MrYuran

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

Recommended Posts

Итак, есть матрица

float matrix[N][M] = {...};

 

есть функция, в которую передается указатель на матрицу и её размерности в виде параметров

 

void foo(float *matrix_ptr, int n, int m);

 

Вопрос простой: каким образом можно внутри функции обратиться к данным массива в виде

 

temp = matrix_ptr[j];

 

средствами чистого си?

 

Единственный вариант, который видится - вычислять смещения вручную. Либо жестко задавать размерность в параметрах функции.

 

Может, есть какое-нибудь волшебное заклинание, приводящее произвольный указатель к массиву нужной размерности?

Share this post


Link to post
Share on other sites

На эту тему есть хорошее высказывание: "В языке С нет многомерных массивов, но есть массивы из одномерных массивов". :)

 

Ваша задача традиционно решается иным заданием исходного массива:

 

// создаем массив массивов NxM:
int i;
float **matrix;
matrix = (float**)malloc( N * sizeof(float*));  // создаем массив указателей на строки
for( i=0; i < N; i++) matrix[i] = (float*)malloc( M * sizeof(float));  // аллокируем строки

// зовем функцию:

func( matrix, N, M);  // заполняет матрицу NxM единичками

// удаляем массив:

for( i=0; i < N; i++) free( matrix[i]);  // удаляем строки
free( matrix);  // удаляем указатель на них

.....

// сама функция определена так:

void func( float **matrix, int N, int M)
{
  int i, j;
  for( i=0; i < N; i++)
    for( j=0; j < M; j++)
      matrix[i][j] = 1;  // заполняем единичками
}

 

Заметим, что, несмотря на "вычурность" инициализации такой матрицы, она поддерживает традиционное обращение к своему элементу - matrix[j].

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

Share this post


Link to post
Share on other sites
Заметим, что, несмотря на "вычурность" инициализации такой матрицы, она поддерживает традиционное обращение к своему элементу - matrix[j].

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

На плюсах как раз можно тут без всяких классов обойтись и решить задачу в исходном виде:

template <typename T, size_t N, size_t M>
int m(T (& a)[N][M])
{

    printf("N: %d, M: %d\n", N, M);
    return a[1][1];        // к примеру, элемент с индексами 1, 1
}

float matrix[5][6] = { ... };

int main()
{
    printf("%f\n", m(matrix) );
    return 0;
}

Share this post


Link to post
Share on other sites
Ваша задача традиционно решается иным заданием исходного массива:

Осталось сделать то же самое, но статически.

Share this post


Link to post
Share on other sites
Осталось сделать то же самое, но статически.

Если писать на Си и есть поддержка стандарта c99 (для GCC включаем -std=c99), то можно так

#include <stdio.h>

float matrix1[3][4] = {
   { 1.0f, 2.0f, 3.0f, 4.0f },
   { 5.0f, 6.0f, 7.0f, 8.0f },
   { 9.0f, 10.0f, 11.0f, 12.0f }
};

float matrix2[4][2] = {
   { 1.0f, 2.0f },
   { 3.0f, 4.0f },
   { 5.0f, 6.0f },
   { 7.0f, 8.0f }
};

void matrix_out(int n, int m, float matrix[n][m])
{
   printf("Матрица[%d][%d]:\n", n, m);
   for (int i = 0; i < n; ++i) {
       for (int j = 0; j < m; ++j) printf("\t%f", matrix[i][j]);
       putchar('\n');
   }
}

int main()
{
   matrix_out(3, 4, matrix1);
   matrix_out(4, 2, matrix2);
   return 0;
}

Share this post


Link to post
Share on other sites
Если писать на Си и есть поддержка стандарта c99 (для GCC включаем -std=c99), то можно так

А ведь сработало!

:08:

 

А всего-то - размерности в параметрах функции объявлены раньше, чем массив

Share this post


Link to post
Share on other sites
А всего-то - размерности в параметрах функции объявлены раньше, чем массив

Ага, и получаем грязный хак из-за зависимости от порядка следования аргументов, что не рекомендуется :(

Share this post


Link to post
Share on other sites
Ага, и получаем грязный хак из-за зависимости от порядка следования аргументов, что не рекомендуется :(

Я пока что проверял результат под цыгвином в винде, а чуть позже буду под mspgcc смотреть.

Посмотрю в листинге, что получится.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this