如何在C函数中使用双指针分配内存?

时间:2012-03-16 13:13:52

标签: c

我想知道如何使用双指针对函数中的char指针进行alloacte内存并写入指针。

我尝试编写以下代码但崩溃了。这有什么错误?

#include <stdio.h>
void myfunc(const char* src, char** dest)
{
  *dest = (char*)malloc(200);
  while(*(*dest++) = (*src++ != '\0'));
  *(*(++dest)) = '\0';
}
void main()
{
 char* src = "hello";
 char* dest = null;
 myfunc(src, &dest);
 printf("%s\n",dest);
}

3 个答案:

答案 0 :(得分:3)

您编写了一个比较循环而不是复制循环('=='vs'='),并且在写入时正在递增错误的指针:

 while(*(*dest++) == *src++);

(附加行:

 *(*(++dest)) = '\0';

是这个问题的最新成员。我不确定我是否想尝试解析它。它不是解决问题的一部分。请参阅下面的讨论。)

最简单的方法是:

 char *tgt = *dest;
 while ((*tgt++ = *src++) != '\0')
     ;

我们可以分阶段纠正你的代码(我这样做了):

static void myfunc(const char* src, char** dest)
{
    *dest = (char *)malloc(200);
    char *tgt = *dest;
    while ((*(tgt++) = *(src++)) != '\0')
        ;
}

这完全括出了循环中的表达式。我们现在可以将*dest替换为tgt

static void myfunc(const char* src, char** dest)
{
    *dest = (char *)malloc(200);
    char *tgt = *dest;
    while ((*((*dest)++) = *(src++)) != '\0')
        ;
    printf("1: %s\n", tgt);
}

这会打印1: hello,但主程序会打印一个空行,因为您已修改*dest,因此它指向复制字符串末尾的NUL '\0'。所以,你需要这样做:

static void myfunc(const char* src, char** dest)
{
    *dest = (char *)malloc(200);
    char *tgt = *dest;
    while ((*((*dest)++) = *(src++)) != '\0')
        ;
    printf("1: %s\n", tgt);
    *dest = tgt;
}

然后main()将打印正确的答案。但是,如果你正在使用tgt('目标'的缩写;我通常使用dst作为目的地,但那距离你的dest太近),那么你可以同时避免首先递增*dest的复杂性。

事实上,你应该考虑使用:

#include <string.h>

...
strcpy(*dest, src);

复制字符串。使用strcpy()可能更好,例如“更快”和“更简单”且更明确无误。


另外,你应该:

#include <stdlib.h>

宣布malloc()

main()的正确返回类型为int

int main()
{
    ...
    return(0);
}

在C99中,(遗憾的是)返回是可选的,如果缺少则返回零(成功);这符合C ++ 98的行为。在早期版本的C中,返回不是可选的。

答案 1 :(得分:0)

在那个小片段中存在很多问题,我不知道从哪里开始...总而言之,你已经使代码变得不必要复杂,因此它最终充满了bug。

需要修复的代码才能编译此代码:

  • 除非这是嵌入式系统的代码,或者除非您正在编写操作员 system,main必须返回int。
  • NULL是C中的大写常量。可以在库stddef.h中找到。
  • malloc函数位于stdlib.h中,必须包含该函数。

严重的错误:

  • 永远不要对malloc的结果进行类型转换。 C FAQthis SO post上的更多信息。
  • 始终释放malloc分配的内存。
  • 您将* src ++!='\ 0'的布尔结果(true / false)指定给一个字符。

广为人知的坏消息&amp;导致错误的危险做法:

  • 始终将指向字符串文字的指针声明为const。
  • 切勿在条件内使用作业。 (MISRA-C:2004 13.1)。
  • 永远不要在复杂表达式中使用++运算符(MISRA-C:2004 12.13)。
  • 切勿在包含循环语句的行的末尾添加分号。 (MISRA-C:2004 14.9)
  • 绝不使用任何没有括号{}的陈述(MISRA-C:2004 14.8)。

风格不佳:

  • main()应该总是返回。
  • 避免使用“幻数”,尤其是在将参数传递给malloc时。
  • 请务必检查malloc()的结果。

有用的提示:

  • calloc将所有已分配的内存设置为零,与malloc不同。如果使用calloc,则不必手动将它们设置为零。

固定代码:

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

#define DYNAMIC_BUF_SIZE 200

void make_string (const char* src, char** dest)
{
  *dest = calloc(DYNAMIC_BUF_SIZE, sizeof(char));

  if(*dest == NULL)
  {
    /* error handling here */
  }

  char* dst = *dest;
  *dst = *src;

  while(*src != '\0')
  {
    dst++;
    src++;
    *dst = *src;
  }
}

void delete_string (char* str)
{
  free(str);
}

int main()
{
  const char* src = "hello";
  char* dest = NULL;

  make_string (src, &dest);
  printf("%s\n",dest);
  delete_string(dest);

  return 0;
}

编辑:根据OP的要求,没有strcpy()的新版本。

答案 2 :(得分:0)

//It seems that you don't understand the nature of char* and char**.
char *str = "hello! I am from China and i want to make friends with foreigners";
char **ptr = {"hello!","i want to learn spoken English","sinalym@163.com"};
//Allocate memory for a char** variable. Two steps as follows:
int length[3] = {6,31,16};
char **ptr2 = new char*[3];
for(int i = 0;i < length[i];i++)
    *(ptr2 + i) = new char [length[i]];
//delete according to a reverse order.