在数组上使用 malloc

Posted

技术标签:

【中文标题】在数组上使用 malloc【英文标题】:using malloc over array 【发布时间】:2012-12-10 10:04:30 【问题描述】:

可能是在 SO 上找到的类似问题。但是,我没有发现,这是场景

案例 1

void main()

    char g[10];
    char a[10];
    scanf("%[^\n] %[^\n]",a,g);
    swap(a,g);
    printf("%s %s",a,g);

案例 2

void main()

    char *g=malloc(sizeof(char)*10);
    char *a=malloc(sizeof(char)*10);
    scanf("%[^\n] %[^\n]",a,g);
    swap(a,g);
    printf("%s %s",a,g);

在这两种情况下我都得到相同的输出。所以,我的问题是我什么时候应该更喜欢malloc() 而不是array 或反之亦然,为什么?我找到了通用定义,malloc() 提供动态分配。所以,这是他们之间唯一的区别??请任何人举例说明,dynamic 的含义是什么,尽管我们在malloc() 中指定了大小。

【问题讨论】:

sizeof char 始终是 1 仅供参考 【参考方案1】:

主要区别在于您决定数组长度的时间和方式。使用固定长度数组会强制您在编译时确定数组长度。相比之下,使用malloc 允许您在运行时决定数组长度。

特别是,在运行时决定允许您根据用户输入和编译时未知的信息做出决定。例如,您可以将数组分配为足够大的大小以适应用户输入的实际数据。如果您使用固定长度的数组,您必须在编译时确定一个上限,然后将该限制强加给用户。

另一个更微妙的问题是,将非常大的固定长度数组分配为局部变量会导致堆栈溢出运行时错误。因此,您有时更喜欢使用 malloc 动态分配此类数组。

【讨论】:

如果您能举例说明,我将不胜感激 @var___ 查看我的答案(并努力理解这一点,这是非常基本的东西......) 是的,我正在尝试一件事,每次都让我感到困惑,dynamic 这个词。也许,我想从你的回答中弄清楚。 在这种情况下,dynamicat runtime 的同义词。对您而言,关键是了解在编译时决定数组长度与在运行时决定之间的区别。 @var___:动态一词与分配请求的内存的时间相关联,而不是与分配的内存量相关联。使用 malloc,您不能在程序执行期间请求分配任意数量的内存。对于称为静态内存分配 (en.wikipedia.org/wiki/Static_memory_allocation) 的数组,因为程序会向编译器指定在编译时本身需要多少内存。另一方面,即使在对 malloc 的调用中指定了需要多少内存,它也不会在调用之前分配。【参考方案2】:

请任何人举例说明,虽然我们指定了大小,但动态是什么意思。

我怀疑这在 C99 之前很重要。在 C99 之前,您不能拥有动态大小的自动数组:

void somefunc(size_t sz)

    char buf[sz];

是有效的 C99,但无效的 C89。但是,使用malloc(),您可以指定任何值,而不必以常量作为参数调用malloc()

另外,为了澄清malloc() 的其他用途:您不能从函数返回堆栈分配的内存,因此如果您的函数需要返回分配的内存,您通常使用malloc()(或其他一些成员malloc 家族的成员,包括realloc()calloc()) 来获取一块内存。要理解这一点,请考虑以下代码:

char *foo()

    char buf[13] = "Hello world!";
    return buf;

由于buf 是一个局部变量,它在其封闭函数的末尾无效 - 返回它会导致未定义的行为。 上面的函数是错误的。 但是,使用malloc() 获得的指针通过函数调用仍然有效(直到你不对其调用free()):

char *bar()

    char *buf = malloc(13);
    strcpy(buf, "Hello World!");
    return buf;

这是绝对有效的。

【讨论】:

【参考方案3】:

我要补充一点,在这个特定示例中,malloc() 非常浪费,因为为数组分配的内存比 [由于 malloc 的开销] 以及调用 malloc( ) 和后来的 free() - 程序员需要记住释放它的开销 - 内存泄漏可能很难调试。

编辑:举个例子,您的代码缺少 main() 末尾的 free() - 在这里可能无关紧要,但它很好地说明了我的观点。

通常应该在堆栈上分配如此小的结构(小于 100 字节)。如果您有大型数据结构,最好使用 malloc 分配它们(或者,如果这样做是正确的,请使用全局变量 - 但这是一个敏感主题)。

显然,如果您事先不知道某个东西的大小,并且它可能非常大(大小为千字节),那绝对是“考虑使用 malloc”的情况。

另一方面,如今堆栈相当大(至少对于“真正的计算机”而言),因此分配几千字节的堆栈并不是什么大问题。

【讨论】:

这个建议很好,只要你在编译时就知道需要多少内存 是的,或者至少你知道“它不会超过这个,并检查它是否超过”。我只是不喜欢“当你不知道输入的大小时使用 malloc”的一般建议 - 有一个 1000 个字符的缓冲区来输入文件名是完全可以的,你不需要通过 getchar 读取文件名和realloc 以确保它完全匹配...

以上是关于在数组上使用 malloc的主要内容,如果未能解决你的问题,请参考以下文章

结构中的数组和结构的 Malloc

剖析C动态内存管理 (malloc,calloc,realloc,柔性数组)

动态数组和功能化 malloc [重复]

C语言中malloc和静态数组最多能开到多大呢

使用 malloc 的 MPI 动态数组

如何使用 malloc 动态声明结构中存在的数组