【问题标题】:How to allocate memory for a int array in a struct如何为结构中的 int 数组分配内存
【发布时间】:2016-01-12 00:24:27
【问题描述】:

我有一个结构

 typedef struct
 {
  int size; //size of array
  int array*
 } 

如何使用 size 变量和 malloc 为 int 数组分配内存?

【问题讨论】:

  • 或者我是否必须做一些初始化函数,如果是这样,那会是什么样子?
  • struct s; s->size=SOME_SIZE; s->array = malloc(s->size * (sizeof *s->array));

标签: c memory malloc allocation


【解决方案1】:

您的问题的答案取决于您是声明struct 还是指向 struct 的指针。如果您声明了一个结构(例如mystruct s),那么您只需为s.array 中的s.size 元素分配内存。例如:

typedef struct mystruct {
    int size;
    int *array;
} mystruct;
...

mystruct s;

s.size = 5;

/* allocating array based on size */
s.array = malloc (s.size * sizeof *s.array);
if (!s.array) {
    fprintf (stderr, "error: virtual memory exhausted.\n");
    return 1;
}

注意:您必须验证分配成功,并且每次调用mallocmalloc 实际上返回了一个有效地址。 (你可以创建一个函数来减少打字)。完成后,您只需要免费的s.array

但是,如果您声明一个 指向 struct(例如mystruct *msp = NULL;)的指针,您现在必须为mspmsp->array 分配内存。示例:

mystruct *msp = NULL;

msp = malloc (sizeof *msp);
if (!msp) {
    fprintf (stderr, "error: virtual memory exhausted.\n");
    return 1;
}

msp->size = 5;

/* allocating array based on size */
msp->array = malloc (msp->size * sizeof *msp->array);
if (!msp->array) {
    fprintf (stderr, "error: virtual memory exhausted.\n");
    return 1;
}

完成后您必须同时free

下面是一个简单的例子,展示了在这两种情况下array 的内存分配、使用和释放:

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

typedef struct mystruct {
    int size;
    int *array;
} mystruct;

int main (void) {

    size_t i = 0;
    size_t nelements = 0;
    int rd = 0;

    /*
     * declaring a struct mystruct
     */
    mystruct s;

    s.size = 5;

    /* allocating array based on size */
    s.array = malloc (s.size * sizeof *s.array);
    if (!s.array) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    /* fill array */
    for (rd = 0; rd < s.size; rd++)
        if (scanf ("%d", &s.array[nelements]) == 1)
            nelements++;

    for (i = 0; i < nelements; i++)
        printf (" s.array[%zu] = %d\n", i, s.array[i]);

    /* free allocated memory */
    free (s.array);

    putchar ('\n');

    /*
     * declaring a pointer to mystruct
     */
    mystruct *msp = NULL;

    /* allocate memory for msp (mystruct pointer) */
    msp = malloc (sizeof *msp);
    if (!msp) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    msp->size = 5;

    /* allocating array based on size */
    msp->array = malloc (msp->size * sizeof *msp->array);
    if (!msp->array) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    /* fill array */
    rd = 0;
    nelements = 0;
    for (rd = 0; rd < msp->size; rd++)
        if (scanf ("%d", &msp->array[nelements]) == 1)
            nelements++;

    for (i = 0; i < nelements; i++)
        printf (" msp->array[%zu] = %d\n", i, msp->array[i]);

    /* free allocated memory */
    free (msp->array);
    free (msp);

    return 0;
}

使用/输出示例

$ printf "2\n4\n6\n8\n10\n12\n14\n16\n18\n20\n" | ./bin/struct_alloc_int
 s.array[0] = 2
 s.array[1] = 4
 s.array[2] = 6
 s.array[3] = 8
 s.array[4] = 10

 msp->array[0] = 12
 msp->array[1] = 14
 msp->array[2] = 16
 msp->array[3] = 18
 msp->array[4] = 20

内存错误检查

在您编写的任何动态分配内存的代码中,都必须使用内存错误检查程序。对于 Linux,valgrind 是正常的选择。滥用内存块的方式有很多,可能会导致真正的问题,没有理由不这样做。每个平台都有类似的内存检查器。它们使用简单。只需通过它运行您的程序即可。

$ printf "2\n4\n6\n8\n10\n12\n14\n16\n18\n20\n" | valgrind ./bin/struct_alloc_int
==20515== Memcheck, a memory error detector
==20515== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==20515== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==20515== Command: ./bin/struct_alloc_int
==20515==
 s.array[0] = 2
 <snip>
 msp->array[4] = 20
==20515==
==20515== HEAP SUMMARY:
==20515==     in use at exit: 0 bytes in 0 blocks
==20515==   total heap usage: 3 allocs, 3 frees, 56 bytes allocated
==20515==
==20515== All heap blocks were freed -- no leaks are possible
==20515==
==20515== For counts of detected and suppressed errors, rerun with: -v
==20515== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

【讨论】:

  • Minor:if ((int)i == msp-&gt;size) 很好奇。与if (i == msp-&gt;size) 相比没有任何优势。如果我们被签名的size 卡住了,那么代码应该会出错或者不会读取任何带有非正数的size - 这意味着重新工作循环。
  • 是的,我同意。在这种情况下,这是霍布森的选择。我不想要for 循环,因为我想要基于成功的scanf 进行增量控制。这里i 的界限对演员来说是安全的。例如i=0; ... i++; if (int)i == msp-&gt;size) ... 但我还是不喜欢它。基于成功的scanf 保留增量的唯一不太优雅的修复方法是添加和初始化int 计数器。例如i=0; int rd=0;... i++,rd++; if (rd == msp-&gt;size) ...,或者干脆用 int 计数器替换 i。 (我想将nelements 保留为size_t)你的想法?
  • 建议for ("same_type_as_msp-&gt;size" i = 0; i &lt; msp-&gt;size; i++) 并退出循环应该scanf("%d", &amp;msp-&gt;array[i]) != 1。如果scanf() 结果为0,则可能在需要特殊处理的stdin 中冒犯char。如果sizesize_t 以外的任何类型,请同意,对于真正可移植的代码,请咨询M. Hobson 并使用fgets()。顺便说一句,很好的完整答案 - 你有我的 +1
【解决方案2】:
int *ptr;
ptr = malloc(sizeof *ptr * size);
//can now reference ptr[0], ptr[1], ... ptr[size-1].

上面的代码做了什么:当你为一个 int 数组分配内存时,你为你需要的每个元素分配了 4 个字节的内存 (sizeof(int))。所以当你 malloc 时,你 malloc 是元素的大小乘以你需要的元素的数量。

【讨论】:

    【解决方案3】:

    你可以创建一个初始化结构的函数,你可以像这样创建一个:

    typedef struct {
        int size; //size of array
        int *array;
    } mystruct;
    
    mystruct * create_mystruct(int size) {
        mystruct * st = (mystruct*) malloc(sizeof(mystruct));
        st->size = size;
        st->array = (int *) malloc(sizeof(int) * size);
        return st;
    }
    

    Here 是一个工作idone 的例子。

    【讨论】:

    • 不客气 :)。还要记住,你必须 free() 你使用 malloc() 保留的所有资源
    • st-&gt;array = (int *) malloc(sizeof(int) * size); 铸造 maloc() 不需要结果。使用 sizeof *pointer 更安全 --> st-&gt;array = malloc(sizeof *(st-&gt;array) * size); 测试 NULL 返回缺失。
    猜你喜欢
    • 2020-02-03
    • 1970-01-01
    • 2018-02-06
    • 2020-09-03
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多