我的课程对我的作业来说足够好,但我知道它不好

Joe*_*Joe 29 c

我刚刚开始为uni工作,它为我提出了一个问题.

我不明白如何在没有内存泄漏的情况下从函数返回字符串.

char* trim(char* line)  {
    int start = 0;
 int end = strlen(line) - 1;

 /* find the start position of the string */
 while(isspace(line[start]) != 0)  {
     start++;
 }
 //printf("start is %d\n", start);

 /* find the position end of the string */
 while(isspace(line[end]) != 0)  {
     end--;
 }
 //printf("end is %d\n", end);

 /* calculate string length and add 1 for the sentinel */
 int len = end - start + 2;

 /* initialise char array to len and read in characters */
 int i;
 char* trimmed = calloc(sizeof(char), len);

 for(i = 0; i < (len - 1); i++)  {
     trimmed[i] = line[start + i];
 }
 trimmed[len - 1] = '\0';

    return trimmed;
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我正在返回一个指向char的指针,这是一个数组.我发现如果我试图通过以下方式制作'修剪'数组:

char trimmed[len];
Run Code Online (Sandbox Code Playgroud)

然后编译器会抛出一条消息,说明在这一行上预期有一个常量.我认为这意味着由于某种原因,在初始化数组时你不能使用变量作为数组长度,尽管有些东西告诉我这不可能是正确的.

所以我通过为char指针分配一些内存来制作我的数组.

据我所知,这个函数可能只是为了它想要做的事情的次优,但我真正想知道的是:

  1. 您通常可以使用变量初始化数组来声明长度,如:

    char trimmed [len];

  2. 如果我有一个类型的数组(char trimmed [])它将具有与char(即char*)指针相同的返回类型.

  3. 如果我通过分配一些内存并将其分配给char指针来创建我的数组,我该如何释放这个内存.在我看来,一旦我返回这个数组,我无法访问它以释放它,因为它是一个局部变量.

Jus*_*ier 15

解决(3) - 完成后,您可以free使用调用代码中新分配的字符串:

char* tmp = trim(myline);

if (tmp != NULL) {
    ....
    free( tmp );
}
Run Code Online (Sandbox Code Playgroud)

但是这会给调用者带来负担,以便记住释放内存.因此,您可以考虑将分配的缓冲区和缓冲区大小传递给trim(),例如:

void trim(char* line, char *trimmed_buf, int trimmed_buf_len){ ... }
Run Code Online (Sandbox Code Playgroud)

尼尔在解决你的其他问题方面表现出色.基本上,数组声明char trimmed[len];将在堆栈上声明一个局部变量,因此虽然在语法上将a 返回char *到此内存是正确的,但它指向的内存位置将不再有效.

  • 虽然很常见,但在调用`free`之前检查`NULL`是没有意义的.`free`函数已经在内部进行了`NULL`测试,再添加一次测试没有增加任何值(相反我认为它通过噪声提供负值). (3认同)

小智 6

要回答您的具体问题,请使用以下语法:

char trimmed[len];
Run Code Online (Sandbox Code Playgroud)

where len是变量,只允许在C99中,而不是在C89或C++中.返回类型确实是a char *,但返回局部变量trimmed会导致未定义的行为,所以不要这样做.如果你在一个函数中动态分配一个数组calloc并返回它,那么使用该函数返回的指针,由函数的调用者来释放它.