【问题标题】:declaring an array vs allocating memory for it [duplicate]声明一个数组与为其分配内存[重复]
【发布时间】:2018-03-18 21:50:33
【问题描述】:

我用 C 语言编写了一个函数,它从用户那里获取 10 个整数并将它们打印出来。

void memoryallocationtest(int number)
{
    // allocate space for 10 integer
    char *input = malloc( 32 * sizeof(char) );
    long *x = malloc( number * sizeof(long) );
    char *ptr;

    printf("please enter 10 integer X consecutively, -2147483648 <= X <= 2147483647)\n");
    /* promts user to enter ith integer
     * converts input string to long value and saves result in x
     */
    for(int i = 0; i < number; i++)
    {
        printf( "%i. Integer:", (i + 1) );
        scanf( "%s", input );
        x[i] = strtol( input, &ptr, 10 );
    }
    free(x);
    free(input);
}

这是一种有效的方法吗?

是否有必要为我的 char 数组“输入”分配和释放空间,或者我应该像 char input[32]; 一样声明它,还是隐含发生的事情?

【问题讨论】:

  • 如果您确实将输入限制为32 字符并将整数数量限制为10,则无需动态分配input(不会返回)。事实上,没有任何东西被退回。您只需要动态分配您希望返回指针的memoryallocationtest 中声明的对象。我会简单地使用char input[32] = "";,如果您返回x,那么您分配的x 很好,但是将您的函数类型更改为long *,并返回x。 (free(x); 有点违背目的不是吗?)
  • @DavidC.Rankin 这似乎是一个不错的答案。我们可以从未回答的问题列表中解决这个问题吗?
  • 好的,我会写出来的。谢谢。

标签: c malloc


【解决方案1】:

为一个由 10 个整数组成的数组静态留出内存是这样完成的(数据位于内存的堆栈部分。)

int array[10];

对于动态分配,数据存在于堆中。

int *array = (int *) malloc(sizeof(int) * 10);

这是一个简单的图像,大致描述了一个典型程序的内存布局:

是否需要为我的 char 数组“输入”分配和释放空间,或者我应该将其声明为 char input[32];还是那是隐含的?

动态分配的优点是您无需事先知道要从操作系统请求多少内存。缺点是更难管理动态分配的内存,更容易受到external fragmentation的影响。当您使用 malloc 时,您所描述的不会隐式发生。

如果你提前知道你需要多少内存(你的整数数组到底有多长),就没有必要使用动态分配(malloc),并且像“char input[32];”这样声明数组完全足够了。

【讨论】:

【解决方案2】:

继续我的评论:

虽然您对语法和正确使用内存分配函数的技术理解很好,但您提供的函数没有多大意义。局部变量的静态声明总是比动态分配内存更快(例如更有效)(如果只是通过节省函数调用开销)。

“我需要动态分配吗?” 之间的选择主要取决于 (1)“是否太大而无法放入堆栈?”,以及(2) “存储值所需的生命周期是多少?” C11 Standard (draft n1570) §6.2.4 Storage durations of objects

您的函数(类型void)不返回任何值,并且对存储在x 中的10 个int 值不执行任何操作。在这方面,正如所写,不需要动态分配任何东西。简单地声明一个字符数组和 long 数组将提供 自动存储持续时间(例如,对于声明它们的函数的生命周期(例如范围))。因此,更有效的函数实现只需声明 char input[32] = "";long x[10] = {0};

注意:当您在函数中声明数组时,数组的内存只保证在函数的生命周期内存在。返回后,函数堆栈(以及该函数本地声明的任何变量)被销毁(例如,内存被释放以供重用),并且任何访问数组值的尝试(或该函数本地的任何变量)之后该函数以未定义的行为返回结果。

现在无论你是否返回x并将你的函数类型更改为long *,都不需要动态分配input,因为不会返回该值。

但是,如果您确实需要返回指向 x 的指针,以便您存储的值可以在调用函数中返回,那么您确实需要像您所做的那样动态分配 x。为什么?当您使用mallocx 动态分配内存时,生命周期从分配内存的时间开始,直到它被释放(参见上面链接中的§7.22.3 内存管理函数) .所以你可以像你一样在你的函数中动态分配x,然后将你的函数声明为long *memoryallocationtest(int number)return x,以使这些值可以在你的程序的其余部分中使用,直到你free (x);

这让我想到了最后一点。你的函数,如所写,填充x,然后立即释放x。虽然很好,但在 x 的实际使用中,free (x); 调用不会发生,直到您以某种有意义的方式完成使用 x

总而言之,如果x 不适合堆栈,或者您决定return x; 为真,则无需为input 分配,那么是的,这是一种非常有效的方法来提供x 的内存是 malloc。但是,如果您只是在函数中使用x,并且它将适合函数堆栈(直到您达到数十万个元素、体系结构和编译器依赖),那么一个简单的@987654349 数组声明@ 就是你所需要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2021-11-15
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    相关资源
    最近更新 更多