2017-04-11 142 views
0

在尝试自己学习C时,我遇到了这个我想开发的简单程序。它只是试图利用指针数组的指针来创建类似于矩阵的东西。我在Windows上编译,当我运行它时,它只是崩溃,同时,在Linux上尝试这个代码它说segmentation fault,这是因为函数参数是数组?我在这里做错了什么?了解指针数组的指针作为函数的参数

#include <stdio.h> 
#include <stdlib.h> 

void initializeArray(float** array, int size); 
void printArray(float** array, int size); 

int main() 
{ 
    float** array_1 = NULL; 
    int array_size = 3; 

    initializeArray(array_1, array_size); 

    // Free memory from array 
    for (int i = 0; i < array_size; i++) 
    { 
     free(array_1[i]); 
    } 

    free(array_1); 

    return 0; 
} 

void initializeArray(float** array, int size) 
{ 
    array = malloc(size * sizeof(float*)); 

    if (array) 
    { 
     for (int i = 0; i < size; i++) 
     { 
      array[i] = malloc(size * sizeof(float)); 
      if (!array[i]) 
      { 
       exit(0); 
      } 
     } 
    } 

    for (int i = 0; i < size; i++) 
    { 
     for (int j = 0; j < size; j++) 
     { 
      array[i][j] = 0; 
     } 
    } 
} 


void printArray(float** array, int size) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     for (int j = 0; j < size; j++) 
     { 
      printf("%f\t", array[i][j]); 
     } 

     printf("\n"); 
    } 
} 

回答

1

做时:

void initializeArray(float** array, int size) 
{ 
    array = malloc(size * sizeof(float*)); 

你不改变后的array外功能使array_1指向NULL(像以前一样)的调用(并创建一个内存泄漏)。您需要将其返回(或将其作为三个指示符***传递并将其作为*array使用,但这不太方便)。

float **initializeArray(int size) 
{ 
    float** array = malloc(size * sizeof(float*)); 
    ... 
    return array; 
} 

,并从主:

array_1 = initializeArray(array_size); 
+2

功能(并且是三星级的程序员不是恭维) –

+0

是,三星级的程序员:你会避免这种情况。 –

+0

@ Jean-FrançoisFabre啊,我明白了,没有注意到,但在那之后,我应该如何在main()中调用函数?分配给'array_1'足够了吗? – lorenzattractor

0

如果你想有一个函数来修改参数的值,则必须将指针传递给该参数:

void foo(T *ptr) 
{ 
    *ptr = new_value(); // write a new value to the thing ptr points to 
} 

void bar(void) 
{ 
    T var; 
    foo(&var); // write a new value to var 
} 

这是真的为任何类型T,包括指针类型。与P *更换T,我们得到

void foo(P **ptr) 
{ 
    *ptr = new_value(); // write a new value to the thing ptr points to 
} 

void bar(void) 
{ 
    P *var; 
    foo(&var); // write a new *pointer* value to var 
} 

基本上,任何的var类型,你需要ptr间接一个多水平。

应用,为您的代码:

void initializeArray(float*** array, int size) 
{ 
    *array = malloc(size * sizeof(float*)); 

    if (*array) 
    { 
     for (int i = 0; i < size; i++) 
     { 
      (*array)[i] = malloc(size * sizeof(float)); // parens matter; you want 
      if (!(*array)[i])       // to index into what array *points 
      {           // to*, not array itself 
       exit(0); 
      } 
     } 
    } 

    for (int i = 0; i < size; i++) 
    { 
     for (int j = 0; j < size; j++) 
     { 
      (*array)[i][j] = 0; 
     } 
    } 
} 

这会从main被称为:

initializeArray(&array_1, array_size); 

一对夫妇的建议:

首先,调用malloc时,使操作sizeof运营商您的取消引用目标,而不是类型名称:

ptr = malloc(N * sizeof *ptr); 

在你的情况,这将是

*array = malloc(size * sizeof **array); // sizeof operand has one more level of 
              // indirection than target 

(*array)[i] = malloc(size * sizeof *(*array)[i]); 

如果你改变的array类型这会保护你;您不必追查sizeof (float)sizeof (float *)的所有实例并更改它们。

其次,你分配的不是一个2D数组 - 它是一个指针数组,每个指针指向一个单独的数组float。这是完全正确的,取决于你在做什么,只要注意行在内存中不相邻 - array[1][2]之后的对象是而不是将会是array[2][0]

如果你想分配一个连续,多维数组,你会使用类似

float (*array)[3] = malloc(3 * sizeof *array); 

那留出空间,为连续3x3的阵列。随着VLA语法,你可以写像

void initializeArray(size_t rows, size_t cols, float (**array)[cols]) 
{ 
    *array = malloc(rows * sizeof **array); 
    if (*array) 
    { 
    for (size_t i = 0; i < rows; i++) 
     for (size_t j = 0; j < rows; j++) 
     (*array)[i][j] = initial_value(); 
    } 
}