修改引用传递的变量vs从函数返回它

时间:2014-02-20 09:42:04

标签: c

根据C FAQ on instantiating a matrix using a double pointer的建议,我偶然发现了另一个问题。我设法解决了这个问题,但很难理解为什么它以某种方式工作而不是另一种方式。

我有以下代码可以使用,然后我会告诉你一点不起作用,我希望你能解释原因:

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

int HEIGHT = 20;
int WIDTH = 20;

int ** curr_grid;

/**
 * Generate an array with the given height and length
 */
int ** create_grid() {
    int ** grid;
    grid = malloc(sizeof(int *) * HEIGHT);
    int row;
    for (row = 0; row < HEIGHT; row++) 
        grid[row] = malloc(sizeof(int) * WIDTH);
    return grid;
}

/* Entry Point main */
int main(int argc, char** argv) {
    curr_grid = create_grid();
    curr_grid[0][0] = 0;
    free(curr_grid); // Release heap resources
    return 0;
}

为网格分配内存并以这种方式返回指针。但是,我首先尝试了另一种方式,我确信它也应该有效,但事实并非如此:

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

int HEIGHT = 20;
int WIDTH = 20;

int ** curr_grid;

/**
 * Generate an array with the given height and length
 */
 create_grid(int ** grid) {
    grid = malloc(sizeof(int *) * HEIGHT);
    int row;
    for (row = 0; row < HEIGHT; row++) 
        grid[row] = malloc(sizeof(int) * WIDTH);
}

/* Entry Point main */
int main(int argc, char** argv) {
    create_grid(curr_grid);
    curr_grid[0][0] = 0; // Segmentation Fault
    free(curr_grid); // Release heap resources
    return 0;
}

这样做会在指示的行上终止分段错误。但是,我的印象是通过引用传递变量允许您修改它。

为什么这不起作用?

3 个答案:

答案 0 :(得分:2)

你没有通过说create_grid(curr_grid);来传递指针的地址  这里它传递curr_grid指针中存在的值(随机值)并将该值带入网格中。一旦函数执行完毕,就会从堆栈中获取它。

尝试传递指针的地址,然后工作正常。

create_grid(&curr_grid);

编辑:检查以下链接,希望它可以帮助您进行图形表示

Pointer tutorial

答案 1 :(得分:1)

你想要这个:

void create_grid(int ***grid) {
    *grid = malloc(sizeof(int *) * HEIGHT);
    int row;
    for (row = 0; row < HEIGHT; row++) 
        (*grid)[row] = malloc(sizeof(int) * WIDTH);
}

/* Entry Point main */
int main(int argc, char** argv) {
    create_grid(&curr_grid);
    curr_grid[0][0] = 0;
    free(curr_grid); // Release heap resources
    return 0;
}

这就像下面的例子:

int MyFunction()
{
  return 3 ;  // we return directly 3
}

void main()
{
  int a ;
  a = MyFunction() ;    
}

VS

void MyFunction1(int *pa)
{
  *pa = 3 ;   // we assign 3 to the memory location pointed by pa
}

void main2()
{
  int a ;
  MyFunction1(&a) ;  // we pass the pointer to a /
  // now a contains 3
}

答案 2 :(得分:0)

知道如何传递任何类型的变量(指针与否,规则保持不变)的方法是:

void create_grid(int **grid) {
    grid = malloc(...);
    ...
}

在这里,您传递一个名为grid的变量,并且您希望更改它的值grid = malloc(...);,但由于您只使用grid而没有任何*,因此您只有一个网格副本  对grids值所做的任何更改都不会在函数外显示。

现在在这种情况下:

void create_grid(int ***grid) {
    *grid = malloc(...);
    ...
}

现在,当您使用和'*'访问网格的值时,您知道,任何以这种方式完成的更改将在函数返回后保留,因为网格实际上是对二维数组的引用。

这很简单(无论变量是什么类型)。