【问题标题】:Realloc into a function重新分配到函数中
【发布时间】:2014-01-30 19:19:41
【问题描述】:

我的问题是关于“realloc”的。 以下代码可以正常工作(没有警告):

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

int main ()
{
    int num=10;
    int *vet;
    int i;

        for (i=0; i<num; i++)
    {
        /* allocate memory of vet to contains (i+1) int */
        vet = (int*) realloc ( vet, (i+1) * sizeof(int) );

        /* write numbers in the allocated memory */
        vet[i] = 321 + i;
    }

    /* print test, if all works I must see:
    | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | */
    printf ("| ");
    for (i=0; i<num; i++)
        printf ("%d | ", vet[i]);
    printf ("\n");

    return 0;
}

但是具有函数的同一个程序不起作用!并且编译器返回以下警告:

In function ‘main’:
14:10: warning: ‘vet’ is used uninitialized in this function [-Wuninitialized]

代码是:

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

void memoria (int *, int);

int main ()
{
    int *vet, num=10;

    memoria (vet, num);

    /* print test, if all works I must see:
    | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | */
    int i;
    printf ("| ");
    for (i=0; i<num; i++)
        printf ("%d | ", vet[i]);
    printf ("\n");

    return 0;
}

void memoria (int *vet, int num)
{
    int i;

    for (i=0; i<num; i++)
    {
        /* allocate memory of vet to contains (i+1) int */
        vet = (int*) realloc ( vet, (i+1) * sizeof(int) );

        /* write numbers in the allocated memory */
        vet[i] = 321 + i;
    }
}

谁能告诉我为什么?非常感谢!

哦,在主要作品中使用“随机”malloc 的相同代码(使用函数)...

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

void memoria (int *, int);

int main ()
{
    int *vet, num=10;

    /* ADDED MALLOC */
    vet = (int*) malloc (1);

    memoria (vet, num);

    /* print test, if all works I must see:
    | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | */
    int i;
    printf ("| ");
    for (i=0; i<num; i++)
        printf ("%d | ", vet[i]);
    printf ("\n");

    return 0;
}

void memoria (int *vet, int num)
{
    int i;

    for (i=0; i<num; i++)
    {
        /* allocate memory of vet to contains (i+1) int */
        vet = (int*) realloc ( vet, (i+1) * sizeof(int) );

        /* write numbers in the allocated memory */
        vet[i] = 321 + i;
    }
}

【问题讨论】:

  • 更改您的函数以接受 int **vet,然后从 main 调用 memoria(&amp;vet, num); 。也不要转换 malloc 或 realloc 的结果,因为它会使有价值的诊断静音,而且看起来很糟糕。
  • 以下代码正常工作(没有警告):第一个代码‘vet’ is used uninitialized也是。
  • gcc version 4.8.1 没有警告(现已测试)!
  • @user malloc 和 realloc 给出一个新的指针,所以你的函数必须能够改变“第一个元素”的开始位置
  • 一些警告,例如未使用的变量,只有在使用优化器时才会产生。它不一定是-O3,但您确实需要在命令行上使用某种形式的-O

标签: c function initialization realloc


【解决方案1】:

你写这篇文章的方式:

int *vet, num=10;

memoria (vet, num);

您在memoria 中所做的更改不会发送回main。要理解这一点,只是为了好玩更改num 的值而不是memoria,然后在main 中检查它。 main 中的值仍然是10。变量vetnum 是按值传递的,因此它们在main 中保持其原始值。

解决这个问题的两种最常见的方法是传递vet 的地址,以便memoria 可以修改它,或者为vet 返回一个新值。

第一个表单如下所示:

memoria( & vet, num ) ;

void memoria (int **vet, int num)
{
  * vet= realloc( * vet, ... ) ;

或者,您可以更改 memoria 的返回类型,

vet= memoria( vet, num ) ;

int * memoria( int * vet, int num)
{
  ...
  return vet ;
}

他们都有自己的优点和缺点。第二种形式可能更容易让那些不是指针的人遵循。

ma​​lloc/realloc 侥幸

如果您将printfs 添加到mainmemoria 以显示vet 的值,则很容易看出上一个示例有效的原因。如果可以,realloc() 会将新内存放在与旧指针相同的位置。在您的简单测试用例中,分配器很容易这样做,因此内存保持在同一位置。如果代码更复杂,并且对realloc() 的调用移动了指针,那么之后您会在main 中看到崩溃。

【讨论】:

  • 感谢您的回答! num 是按值传递的,没关系,因为我不想改变它,但是vet?使用memoria (vet, num);,我将指针传递给函数,对吗?
  • @user。是的,您传递了一个指针,但是您的函数 更改 自身内部的指针(vet = realloc(vet,...) 但不会将修改后的指针返回到 main()
  • 谢谢,我明白了!但是如何解决问题呢? (为什么我发布的最后一个代码有效?)
  • @woolstar。如果我想在第一个表单函数中使用scanfsscanf (buff, "%d", vet[i]); 不起作用!
  • 是的,因为vet 不再是int *
【解决方案2】:

处理好这几个问题,一切顺利。

您的main 没有返回实际上指向某事的vet。以某种方式将vet 返回到您的main vet

int *vet = NULL; //better bet for realloc() in this case
vet= memoria (vet, num);

相应地更改原型以返回一个指针,并记住在定义中返回vet

int* memoria(int*, int);

现在到realloc()。根据ISO C

如果 ptr 是 null pointer,则 realloc() 应等同于 malloc() 为指定的大小。

如果 ptr 不匹配 calloc() 之前返回的指针, malloc()realloc() 或者如果空间先前已被释放 通过调用free()realloc(),行为未定义。

希望对您有所帮助。

【讨论】:

  • 非常感谢!那么,例如,对于一个结构struct example *e; 是一样的吧?你现在为什么我发布的最后一个代码有效?谢谢!
  • 还有一个问题:如果我想用 void 函数解决问题?
  • 是的。在您的最后一个 sn-p 中,vet 只是一个指针,它指向您分配的内存块。您已将此指针传递给重新分配它的函数。 realloc() 返回一个新的指针值,其值 可能可能不 与旧指针值相同。并且您的旧内容以某种方式保留了!
  • 好吧,如果您要在 void 函数 中重新分配相同的内存,恐怕如果不处理一些未定义的行为,我们就无法做到。
【解决方案3】:

您正在将未初始化的 vet* 传递给 realloc。 Realloc() 类似于 free() 以防它分配全新的内存(它 free()s 旧分配)。所以任何传递给 realloc() 的指针最好是一个有效的堆指针或空指针。

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2019-06-12
    • 2016-06-27
    • 2017-12-13
    • 2018-05-26
    • 1970-01-01
    相关资源
    最近更新 更多