我可以使用“malloc”为局部变量返回局部变量吗?

时间:2017-08-02 02:23:50

标签: c

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

char * upperCase(const char* s)
{
    char * ret = NULL;
    size_t length = strlen(s) + 1;
    ret = (char*)malloc(sizeof(char) * length);
    for (size_t i = 0; i < length; i++) {
        ret[i] = toupper(s[i]);
    }
    return ret;
}

int main()
{
    char* ret = NULL;
    char* input = "HelloWorld";
    ret = upperCase(input);
    printf("value = %s", ret);
    free(ret);
}
  

上面的代码将字符串作为参数并复制字符串。它   然后将复制的字符串的每个元素转换为大写和   退货。

     

编译器= GCC 6.2

如果使用malloc函数,是否可以返回局部变量来终止函数并释放内存?我对仍有记忆的范围知之甚少。

2 个答案:

答案 0 :(得分:4)

简短回答:是的,可能

长答案malloc(some_size)分配some_size空格并返回指向已分配块的开头地址的指针(或失败时为NULL)。在执行ret = (char*)malloc(sizeof(char) * length);时,会为ret分配指向length char的内存块的指针(请注意sizeof(char) == 1,以便将其删除)。

即使在函数返回后,内存也是你的,直到你释放它为止,因此,在upperCase(...)执行结束后,该内存仍然属于你。唯一的问题是,指针ret是在具有(auto)本地存储的堆栈上分配的,这意味着它将&#34; die&#34; 范围(在您的情况下 - upperCase(...)函数的范围),因此,您将无法知道该内存的位置,但是,因为您从ret返回main函数,它所拥有的值(这是你分配的内存的地址)将传递给ret int increment_by_one(int x){int y = x + 1; return y;},这基本上意味着你很高兴。

我认为我应该强调的最后一件事是,返回局部变量一直在进行。例如int y。这是一个非常简单的函数,它返回本地x+1的值。由于返回的值是我们所需要的(即ret的值),因此它(值)存储在局部变量中是可以的。同样(有点)适用于您的情况 - 因为upperCase内的upperCase包含已分配的地址,因此&#34; die&#34; <{1}}结束后的,因为传递的值(地址)被传递。

char * upperCase(const char* s)
{
    char * ret = NULL;                             // local variable -> will die after upperCase ends
    size_t length = strlen(s) + 1;                 // local variable -> will die after upperCase ends
    ret = (char*)malloc(sizeof(char) * length);    // ret assigned with address to memory
    for (size_t i = 0; i < length; i++) {          // local variable -> will die after it's scope (the for loop) ends
        ret[i] = toupper(s[i]);
    }
    return ret;                                     // said address is returned to main (local variable ret now dies peacefully after fulfilling its duty) 
}

int main()
{
    char* ret = NULL;               // local variable -> will die after main ends
    char* input = "HelloWorld";     // local variable -> will die after main ends
    ret = upperCase(input);         // ret gets the address allocated in upperCase
    printf("value = %s", ret);
    free(ret);                      // address is freed
}

2注:

  1. 不需要转换malloc返回值,这意味着ret = (char*)malloc(sizeof(char) * length);应为ret = malloc(sizeof(char) * length);
  2. 不需要sizeof(char),因为它1,这意味着您可以将其进一步缩短为ret = malloc(length);
  3. malloc可能会失败。在这种情况下,它会返回NULL,因此在每ret = malloc(...);后,您应该检查if(!ret){// handle error}if(ret != NULL){// do something}等值

答案 1 :(得分:2)

是的,你可以。

malloc内存在堆上,因此在upperCase结束时不会释放。

但是变量char *ret在堆栈中,当upperCase结束时它将弹出。但retupperCase()的值已通过ret = upperCase(input)中的main()复制。也就是说,您仍然可以获得已分配内存的地址,该内存仍在堆上。完成使用此内存后,您可以调用free(ret)

检查What and where are the stack and heap?以获取有关堆栈和放大器的详细信息。堆。