2010-08-18 3 views
10

Как передать матрицу m в foo()? если мне не разрешено изменять код или прототип foo()?Передача двумерного массива с помощью указателя

void foo(float **pm) 
{ 
    int i,j; 
    for (i = 0; i < 4; i++) 
     for (j = 0; j < 4; j++) 
      printf("%f\n", pm[i][j]); 

} 

int main() 
{ 
    float m[4][4]; 

    int i,j; 
    for (i = 0; i < 4; i++) 
     for (j = 0; j < 4; j++) 
      m[i][j] = i+j; 

    foo(???m???); 
} 

ответ

8

Если вы не можете изменить foo(), вам нужно будет изменить m. Объявите его как float **m и соответствующим образом распределите память. Затем позвоните по номеру foo(). Что-то вроде:

float **m = malloc(4 * sizeof(float *)); 
int i, j; 
for (i = 0; i < 4; i++) 
{ 
    m[i] = malloc(4 * sizeof(float)); 
    for (j = 0; j < 4; j++) 
    { 
     m[i][j] = i + j; 
    } 
} 

Не забудьте free() впоследствии!

+0

Техника, которую вы используете не имеет никакого отношения к динамическим распределение памяти вообще. Поскольку размеры массива постоянны, вы можете просто выделить память «в стеке», как и в OP. – AnT

+0

Конечно, но это не так - решение проблемы заключается в изменении типа m. –

+0

@ Карл Норум: Не обязательно. Проблема, как указано, кажется, подразумевает, что существующая 'foo' должна быть сделана для работы с существующим' m'. И решение проблемы заключается в изменении типа того, что передается 'foo', а не типа' m'. – AnT

0

foo(m) Не работает?

+1

Нет, это не так. 2D-массив не является указателем на указатель. –

+0

О, давно я использовал C и указатели (возможно, 20 лет). – Frank

14

Если вы настаиваете на приведенном выше объявлении foo, т.е.

void foo(float **pm) 

и с помощью встроенного в 2D массива, т.е.

float m[4][4]; 

тогда единственный способ сделать свой foo работу с m - создать дополнительный массив «индекс строки» и передать его вместо m

... 
float *m_rows[4] = { m[0], m[1], m[2], m[3] }; 
foo(m_rows); 

Невозможно пройти m до foo. Это невозможно. Тип параметра float ** безнадежно несовместим с аргументом типа float [4][4].

Кроме того, поскольку C99 выше, может быть выражена в более компактном виде, как

foo((float *[]) { m[0], m[1], m[2], m[3] }); 

P.S. Если вы посмотрите внимательно, вы поймете, что это в основном то же самое, что и Карл Норум в своем ответе. За исключением того, что Carl - это malloc - память массива, которая не является абсолютно необходимой.

+0

Carl также является «malloc» - каждая строка отдельно, в то время как пример AndreyT оставляет фактические данные в одном блоке. – caf

3

Вы не можете. m несовместим с аргументом foo. Вам придется использовать временный массив указателей.

int main() 
{ 
    float m[4][4]; 
    int i,j; 

    float *p[4]; 

    p[0] = m[0]; 
    p[1] = m[1]; 
    p[2] = m[2]; 
    p[3] = m[3]; 

    for (i = 0; i < 4; i++) 
     for (j = 0; j < 4; j++) 
      m[i][j] = i+j; 


    foo(p); 
0

void foo(float **pm) такое же, как void foo(float *pm[]), который не двумерный массив поплавки. Это массив из float*. Теперь эти float* могут сами указывать на массивы с плавающей точкой, но это отдельное дело.

0
typedef float Float4[4]; 

void foo(Float4 *pm) 
{ 
    int i,j; 
    for (i = 0; i < 4; i++) 
    for (j = 0; j < 4; j++) 
     printf("%f\n", pm[i][j]); 
} 

main() 
{ 
    Float4 m[4]; 

    int i,j; 
    for (i = 0; i < 4; i++) 
    for (j = 0; j < 4; j++) 
     m[i][j] = i+j; 

    foo(m); 
    return 0; 
} 
+2

Как это удовлетворяет требованию * «Мне не разрешено изменять код или прототип foo()?» *? – caf

2

Если у вас есть компилятор, который поддерживает C99, текущий стандарт C, то вы можете сделать это:

foo((float *[]){ m[0], m[1], m[2], m[3] }); 

(Обратите внимание, что это точно так же, как ответ AndreyT «s, за исключением того, что он воздерживается от того, чтобы назвать временный массив)

2
  • вам не нужно делать какие-либо изменения в основной, но функция будет работать должным образом, если изменить формальный прототип вашей функции (* pm) [4] или pm [] [4], потому что ** pm означает указатель на указатель целых чисел, а (* pm) [4] или pm [] [4] означает указатель на poiner из 4 целых чисел.

    m здесь также является указателем на указатель 4 целых чисел, а не указателем на указатель целых чисел и, следовательно, несовместим.

    #include<stdio.h> 
    void foo(float (*pm)[4]) 
    { 
        int i,j; 
        for (i = 0; i < 4; i++) 
         for (j = 0; j < 4; j++) 
          printf("%f\n", pm[i][j]); 
    
    } 
    
    int main() 
    { 
        float m[4][4]; 
        int i,j; 
        for (i = 0; i < 4; i++) 
         for (j = 0; j < 4; j++) 
           m[i][j] = i+j; 
    
        foo(m); 
    } 
    
0

Использование C99, который поддерживает массивы размером во время выполнения, следующий возможный способ передать 2-тусклый массив:

void foo(void *pm, int row, int col) 
{ 
    float (*m)[col] = pm; 

    for (int i = 0; i < row; i++) 
     for (int j = 0; j < col; j++) 
      printf("%4.1f%s", m[i][j], (j == col-1)?"\n":" "); 

} 

int main() 
{ 
    float m[4][4]; 

    for (int i = 0; i < 4; i++) 
     for (int j = 0; j < 4; j++) 
      m[i][j] = i+j; 

    foo(m, 4, 4); 

    return 0; 
} 
Смежные вопросы