【问题标题】:Dynamic array, passing addresses动态数组,传递地址
【发布时间】:2019-01-25 07:56:00
【问题描述】:

我想创建一个函数,它的参数是我动态分配的二维数组,问题是我不知道如何构建我的函数。

这是我的主要内容(N_MAX 定义为 300):

int i;
int **Bord = NULL;

Bord = malloc(N_MAX * sizeof(*Bord));
if(Bord == NULL)
{
    printf("Error while allocating memory to an array");
    free(Bord);
    return -1;
}
for(i = 0; i < N_MAX; i++)
{
    printf("%d\n", i);
    Bord[i] = malloc(N_MAX * sizeof(*(Bord[i])));
    if(Bord[i] == NULL)
    {
        printf("Error while allocating memory to an array");
        while(i != 0)
        {
            free(Bord[i]);
            i--;
        }
        free(Bord);
        return -1;
    }
}

我试图用一个不是动态分配的数组做一些事情,但这真的很糟糕。当我想调试函数时,我的手表可以工作(我的数组中有正确的数字)但程序不工作(错误:一元'*'的无效类型参数(有'int'))

我已经在 Google 上进行了一些搜索,但我找不到具有“动态分配”和“通过引用”的主题,如果存在,请告诉我。

如何构建这个功能?

【问题讨论】:

  • 你的新函数应该做什么?
  • 如果是整数,您正在创建一个指向数组的指针数组;您没有创建 2D 数组,因为 2D 数组中的所有元素都是连续的。两者都可以使用两个下标访问,但底层数据却大不相同。
  • 有点难解释,但数组中有一张图片,这张图片上有线条。该程序必须遵循这些路线。因此,该函数获取直线的一个坐标并查找该点周围的内容。最后返回下一点的坐标。
  • 那么,如果它们不连续,我如何通过引用传递我的数组?有可能吗?
  • 您可以将指针传递给指向函数的指针数组的开头;数组中的指针彼此连续。每个整数数组中的整数(在第二个循环中分配)是连续存储的;但是,不能保证Bord[0] 中的整数与Bord[1] 中的整数是连续的。您需要将int **data 传递给您的函数。然后,您可以使用双下标访问数组的元素:data[i][j] 等。但是,汇编代码与使用 int (*data)[N_MAX](指向数组的指针)使用的代码完全不同。

标签: c function multidimensional-array dynamic pass-by-reference


【解决方案1】:

这是一个简单的程序,它说明了两个函数——init_array() 在(或多或少)问题中的代码创建数组后初始化数组,print_array() 打印数组中的值。除了合理的职责分离之外,这两个函数表明init_array() 中设置的内容在print_array() 函数中是可见的。还有一个很小的函数free_array(),叫做static inline,它释放数组的分配数据——它处理部分和完全分配的数组。除了main() 之外的所有函数都标记为static,因为没有其他文件需要查看任何函数。请注意,为了便于测试,我将 N_MAX 设置为 8,而不是 300。现在我知道它正在工作,将 N_MAX 设置为 300 是可行的,也许是明智的。

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

static void print_array(int **base);
static void init_array(int **base);

enum { N_MAX = 8 };

static inline void free_array(int n_rows, int **array)
{
    for (int i = 0; i < n_rows; i++)
        free(array[i]);
    free(array);
}

int main(void)
{
    int i;
    int **Bord = NULL;

    srand(time(0));     // Not good, but better than nothing

    Bord = malloc(N_MAX * sizeof(*Bord));
    if (Bord == NULL)
    {
        fprintf(stderr, "Error while allocating %zu bytes of memory\n", N_MAX * sizeof(*Bord));
        return -1;
    }
    for (i = 0; i < N_MAX; i++)
    {
        Bord[i] = malloc(N_MAX * sizeof(*(Bord[i])));
        if (Bord[i] == NULL)
        {
            fprintf(stderr, "Error while allocating %zu bytes of memory\n", N_MAX * sizeof(*Bord[i]));
            free_array(i, Bord);
            return -1;
        }
    }

    init_array(Bord);
    print_array(Bord);
    free_array(N_MAX, Bord);
    return 0;
}

static void init_array(int **base)
{
    for (int i = 0; i < N_MAX; i++)
    {
        for (int j = 0; j < N_MAX; j++)
            base[i][j] = (100 * (i + 1)) + (10 * (j + 1)) + rand() % 10;
    }
}

static void print_array(int **base)
{
    for (int i = 0; i < N_MAX; i++)
    {
        printf("[%d]:", i);
        for (int j = 0; j < N_MAX; j++)
            printf(" %3d", base[i][j]);
        putchar('\n');
    }
}

请注意,它使用time() 来初始化随机数生成器,因此它通常应该在每次调用时生成一组新的数字,除非您在一秒钟内多次调用它。

[0]: 115 121 137 142 159 166 175 181
[1]: 211 224 239 248 253 265 277 283
[2]: 316 320 337 349 357 364 376 380
[3]: 419 428 439 448 451 469 476 484
[4]: 511 527 534 544 558 569 578 585
[5]: 616 623 631 647 650 664 671 688
[6]: 710 729 739 748 759 766 779 783
[7]: 817 824 839 847 850 860 878 881

【讨论】:

  • 非常感谢,我已经重写了我的函数,现在它可以工作了。我还有一个问题,inline 表示执行起来会更快,对吧?那是我在另一个线程上读到的。谢谢
  • 使用inline 是对编译器的一个提示,即Jayne 这个函数应该被写入调用它的函数中,而不是作为一个单独的函数。它可以提高性能。这里并不完全清楚这很重要,但它足够小,它可能会有所帮助。但您不太可能衡量这段代码的差异。
【解决方案2】:

在尝试猜测您的“新”功能将是什么样子之前,让我们更正已发布代码的(许多)问题。

// added missing `#include` statements
#include <stdio.h>
#include <stdlib.h>

// added missing definition of N_MAX
#define N_MAX 300 

int main( void )  // corrected signature for 'main'
{
    //int i;
    // minimize the scope of variables

    int **Bord = NULL;

    //edited following line
    Bord = malloc(N_MAX * sizeof(*Bord));
    if(Bord == NULL)
    {
        //printf("Error while allocating memory to an array");
        // error messages should be output to 'stderr', not 'stdout'
        // suggest:
        perror( "malloc failed" );
        //free(Bord);  DONT do this, the allocation was not successful
        return -1;
    }

    // implied else, malloc was successful

    for( int i = 0; i < N_MAX; i++)
    {
        printf("%d\n", i);

        Bord[i] = malloc(N_MAX * sizeof(*(Bord[i]));
        if(Bord[i] == NULL)
        {
            //printf("Error while allocating memory to an array");
            // error messages should be output to 'stderr', not 'stdout'
            // suggest:
            perror( "malloc failed" );

            //while(i != 0)
            // this will not free the first sub allocation
            // suggest
            i--;
            while( i >= 0 )
            {
                free(Bord[i]);  
                i--;
            }

            free(Bord);
            return -1;
        }
    }

    // the following will result in a memory leak
    // because all those memory allocations have not been passed to 'free()'
    return 0;
}

【讨论】:

  • 你在//Bord = malloc(N_MAX * sizeof(*Bord)); 中的“改进” — // don't want to allocate room for a bunch of 'int's// do want to allocate room for a bunch of pointersBord = malloc( N_MAX * sizeof( Bord ) ); 不是进步,而是倒退。由于指向int 的指针和指向int 的指针具有相同的大小,因此您实际上不会遇到错误,但符号SomeType *data = malloc(number * sizeof(*data)); 是正确的习惯用法,而您的替换不是。如果SomeType 是一个大结构,那么差异将很重要。
  • 好的,我会修改我的答案
  • 请注意,错误路径中的free(Bord); 毫无意义,并无害处。除了不必要的函数调用之外,释放空指针是无操作的。我同意while (i != 0) 循环不会释放第零个数组。不过,我很想只使用while (i &gt; 0) free(Bord[--i]); 作为循环。这不会尝试释放刚刚失败的分配(因为指针为空,所以再次无操作),并且会清理第零个元素并且不会重复自身。
  • 感谢您的回答,是的,我的代码不正确,我只是将“main”中的内容放入其中。乔纳森,我认为我的错误在于,如何调用函数function(int **array),稍后在我的代码中我正在编写function(Bord);
  • @Asusio:你没有显示你的调用代码或你的函数,所以我们不可能猜到你做错了什么。作为一个表达式,***array[0][0] 暗示了五个间接级别——这让我大吃一惊。我们无法帮助您调试我们看不到的代码。请编辑您的问题以在该功能上尽最大努力。它可以明智地安排初始化和打印值。在调试并使代码正常工作时,您可以明智地将 N_MAX 设置为 5 或 10。稍后将其更改为 300 将是微不足道的 - 只要您小心。
猜你喜欢
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多