0

动态分配内存有四种方式,这四种方式有区别吗? 首先像这样:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    // using 'seq'
}

第二个是这样的:

char *seq;
void exam(char *seq){
    seq=(char *)malloc(100*sizeof(char));
    // using 'seq'
}

第三个是这样的:

char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
    char *change=(char *)malloc(100*sizeof(char));
    free(seq);
    seq=change;
    // using 'seq'
}

第四个是这样的:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    free(seq);
    seq=(char *)malloc(100*sizeof(char));
    //using 'seq'
}

你应该知道,我将在方法“exam”之外使用变量“seq”。 请解释一下上面的代码,非常感谢。

4

6 回答 6

2

如果您打算在考试之外使用 seq,则只有第一种情况有效。

其他三种情况收到分配给 seq 的地址,但无法更改它。

要更改 seq 的值,您需要为其返回一个新值,或者显式修改 seq 中的内容。

您需要调查 Pass by Value 以了解为什么这不起作用。请参阅此页面

于 2009-08-07T03:22:33.357 回答
1

这完全取决于你想要做什么。如果可能,最好在同一范围内执行 malloc/free,IMO,它使代码更具可读性 - C 中的内存分配已经够难了。在您的情况下,您将首先 malloc,调用函数,然后在函数外部释放。但当然,这并不总是可能的。

您的某些解决方案将不起作用:例如,第二个解决方案不会做您想做的事情,因为当您调用该函数时,会复制指针:

char *p;
function(p);

void function(char *q) {
    // q is a copy of p, so when q is set by malloc, it will not be reflected in p
    q = malloc(100);
}

一般来说,你应该像 fopen 函数那样做:你返回一个指针:

char* p function() {
    char* ret;
    ret = malloc(100);
    return ret;
}

char *p = function();

或者您可以使用指向指针的指针:

char *p;
function(&p);

void function(char **q) {
    // q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
    *q = malloc(100);
}

不过,总的来说,我认为第一个要好得多。

此外,关于您的风格: sizeof(char) 是无用的,根据定义,无论您使用什么编译器/平台,它始终等于 1,并且强制转换 malloc 是无用的并且实际上是危险的(因为它隐藏了声明 malloc 的缺少的标头包含)。只有在 C++ 中使用 malloc 时它才有用(强制转换)。

于 2009-08-07T03:23:15.650 回答
1

可能有很多方法可以做你正在做的事情。如果您打算在函数之外使用 seq,则您概述的第一种方法将起作用。

如果您打算在调用函数后使用 seq ,那么您还有其他问题。由于 C 是按值传递的,因此您将 seq 中包含的地址传递给例程,这不会更改最后三个示例中与 seq 关联的内存位置。要更改 seq 的内存位置,您需要将指针的地址传递给例程以设置指针。这在 David Cournapeau 的例子中得到了展示。

最后两种情况的问题是您“释放”了内存,但您仍然保留指向内存的指针,因为 seq 的值不会更改,您可以使用它来访问您“释放”的内存。这被称为悬空指针。

David Cournapeau 建议使用函数返回指针将使您能够访问在函数中分配的内存。否则,您需要将 seq 的地址传递给例程并取消引用该值以将其设置为分配的空间。

于 2009-08-07T04:12:02.353 回答
1

除非您使用早于 1989 年 ANSI 标准的 C 实现,或者您打算将此代码编译为 C++,否则不应转换 malloc() 的结果,在这种情况下,您应该使用 new 而不是 malloc();首先,没有必要,其次,如果您在范围内没有 malloc() 的原型,它将掩盖编译器诊断。

此外, sizeof(char) 根据定义为 1;在这种情况下使用它没有任何区别,只会增加视觉噪音。

为任何类型 T 编写 malloc() 语句的规范形式是

T *p = malloc(count * sizeof *p);

或者

T *p;
...
p = malloc(count * sizeof *p);

现在解决你的四个案例......

您的第一个案例通常是正确的;您正在为考试之外的 seq 分配内存,并按值传递指针。

您剩下的案例都有类似的问题;对指针值 seq 的更改不会反映在调用者中,并且您将引入内存泄漏。如果你传递一个指向函数的指针,并且你希望指针值被覆盖,那么你需要传递一个指向该指针的指针:

char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }

如果要调整动态分配的缓冲区大小,请使用 realloc():

char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq) 
{
  char *tmp = realloc(*seq, 100);
  if (!tmp) 
  {
    /* realloc failed */
  }
  else
  {
    *seq = tmp;
    ...
  }

注意

char *p = realloc(NULL, 10);

是相同的

char *p = malloc(10);
于 2009-08-07T17:58:47.940 回答
0

我认为这些是范围上的差异

于 2009-08-07T03:16:09.497 回答
0

为了对这种情况有所了解,请考虑以下重写:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    // using 'var'
}
//--
char *seq;
void exam(char *var){
    var=(char *)malloc(100*sizeof(char));
    // using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
    char *change=(char *)malloc(100*sizeof(char));
    free(var);
    var=change;
    // using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    free(var);
    var=(char *)malloc(100*sizeof(char));
    //using 'var'
}

你打电话时

exam(seq);

以上版本与您的原始版本相同。

于 2009-08-07T03:26:40.353 回答