函数中str [strlen(src)+1]和char * str =(char *)malloc((strlen(src)+1)* sizeof(char))之间的区别

时间:2016-01-30 11:02:38

标签: c arrays pointers malloc heap

我很困惑。有什么区别:

char *someFunction(char *src) {
    char str[strlen(src) + 1];
    ...
    return str;
}

char *someFunction(char *src) {
    char *str = (char*)malloc((strlen(src) + 1) * sizeof(char));
    ... 
    return str;
}

第一个是数组(char[]),第二个是malloc。 我在学校学到的是,如果我想在函数中创建一个新的字符串,我应该使用malloc。但是,它也可以在函数中使用char[](如第一个)。 老师说我们必须使用"堆区域",如果必须动态分配东西。 我认为第一个带数组(char str[..])也是动态的,因为char[]的大小在程序开始之前实际上并不知道(这是正确的理解!?)。这个由我的编译器工作没有任何问题。

请轻松解释其中的差异并告诉我一些必须使用malloc以及我不需要使用它的情况。

5 个答案:

答案 0 :(得分:3)

  

我认为第一个带数组(char str[..])也是动态的,因为char[]的大小在程序开始之前实际上并不知道(正确理解!?)

没有。您使用自以来添加的的可变长度数组功能。这不是动态分配 一旦函数完成其执行str将不再存在,返回指针将调用未定义的行为。

答案 1 :(得分:2)

区别很简单:

  • 第一个使用C99语法在自动存储中分配VLA(通常是堆栈上的 )。此数组只能在函数调用期间使用,不能返回指向它的指针,当调用者使用此返回值时,它将导致未定义的行为。此版本不正确。

  • 第二个从堆中分配一个数组,可以在函数调用结束之后使用,直到freerealloc显式释放它为止。这种类型的分配通常被称为 dynamic ,这个词在英语中有更广泛的含义,但在这种情况下却没有。

请注意,您应该以这种方式简化分配:

char *someFunction(char *src) {
    char *str = malloc(strlen(src) + 1);
    .... 
    return str;
}
根据定义,

sizeof(char)1,在malloc中投放C的返回值通常是一个坏主意,尽管在C++中有必要,但是其他分配方法无论如何都是C++的首选。

请注意,您可以使用Posix函数malloc获取由src strdup(src)分配的副本。

当在当前函数结束后使用内存时,应使用malloc及其变体分配的内存。如果大小很重要,您还应该使用malloc来避免因耗尽自动存储而调用未定义的行为。限制因系统而异,但在现代环境中,自动存储通常可以为所有当前函数调用处理至少一兆字节,超出我建议使用堆存储的范围。

答案 2 :(得分:1)

使用VLA(第一个示例)表示函数返回时数组将不再存在。如果调用者尝试使用函数的返回值,则会显示未定义的行为。 VLA仅保证与符合1999 C标准(或更高版本)的编译器一起使用。

使用malloc()(第二个示例)意味着在函数返回时不会释放数组(除非您的代码也显式调用free())。因此调用者可以安全地使用该版本函数的返回值。代码将与所有C标准(从1989/1990到今天),甚至一些早期的编译器一样。

答案 3 :(得分:0)

  • 在第一个中,您声明一个具有自动存储持续时间的对象。因此只要存在调用它的函数,数组就会存在。在第二种情况下,您将获得具有动态存储持续时间的内存,这意味着它将一直存在,直到它被免费显式释放。
  • 在C堆栈中为本地变量分配,堆用于malloc.So如果用char str[n]声明大型数组,则可能超出堆栈的存储空间,这将导致段错误

答案 4 :(得分:0)

当你声明一个像ckar [something]这样的变量时,它会保存在堆栈中而不是堆中。这不是动态分配。如果你想动态地分配memmory你应该使用malloc并且数组将保存在堆中