为什么我们需要calloc(或malloc)?

时间:2014-05-13 10:38:10

标签: c dynamic-allocation

在我整个CS职业生涯中忽略了C后,我决定试一试!

初始化变量时,我们可以:

int b = 0;

初始化b,为其分配内存,稍后我们可以用

更新它
b = 2;

如果需要的话。

所以,原谅我这个荒谬的“noob”问题,但为什么我们需要这样的电话:

double *b = (double *) calloc(n, sizeof(double));

初始化变量时会为它分配空间吗?

为什么我们不能只做

double b = 0;
b* = b.addressOf(b) //or some similar construct.

这有什么用?

我试过谷歌搜索无效,所以请原谅我 - 很遗憾*在谷歌是一个通配符,因此很难找到相关的结果。

4 个答案:

答案 0 :(得分:3)

在当前上下文中声明的变量在上下文结束时终止它们的生命周期。

分配内存为您提供了存储寿命较长变量的空间。

例如,

double *foo() {
    double d;
    return &d;
}

void bar() {
    double *d = foo();
    *d = 0.0;
}

将尝试访问不再存在的变量,因为它的生命周期是foo函数。

C和C ++不跟踪对象。指针只指向对象,但不会延长对象的生命周期,因此即使指针不是NULL,指针也完全有效。

但是,这是有效的:

double *foo() {
    return (double *)malloc(sizeof(double));
}

void bar() {
    double *d = foo();
    *d = 0.0;
}

这将为double分配内存,并将指针返回到内存,该内存在使用free函数显式返回池之前保持有效。不将它返回池将导致内存泄漏。

答案 1 :(得分:0)

除非我完全弄错,否则在C中,callocmalloc是实现动态数据结构的唯一可能性。

答案 2 :(得分:0)

关于变量分配,您可以这样做:

  1. 静态堆叠,只需:int a = 10。这些变量在堆栈上定义,最有可能与使用它们的一些代码一起定义(这就是为什么在没有正确检查boudadries的情况下写入堆栈中声明的数组可能会很危险。您可能会覆盖代码)。变量还有一个范围:函数范围,全局范围和其他范围(例如if-else的if-branch)。它们使用起来很快,但它们或多或少都是静态的,并且它们具有您不需要清洁它们的巨大优势。它们由应用程序自动清理。但是它们有很大的缺点。堆栈空间比堆空间更有限。因此,您只能使用适度大小的变量(不要从字面上理解,而是对您的操作系统允许进行一些研究。对所有人来说,64KB是不够的。)。
  2. 使用calloc()或其他内存分配函数动态地在堆上。这些变量在称为堆或动态内存的区域中声明。这些变量将保留在那里,直到使用它们的应用程序退出(在这种情况下(现代)操作系统通常将内存回收给自己),或者它们free使用free()。你总是应该释放内存以避免内存泄漏。动态内存的优势在于(在现代操作系统上)可寻址内存远大于分配给堆栈空间的大小,因此您可以拥有更多,更大,更大的结构和数组。

答案 3 :(得分:0)

范围是可以访问变量的代码的区域或部分。可以

  1. 文件范围
  2. 功能范围
  3. 块范围
  4. 计划范围
  5. 原型范围
  6. 实施例

    #include<stdio.h>
    
    void function1()
    {
        printf("In function1\n");
    }
    
    static void function2()
    {
        printf("In function2\n");
        {
            int i = 100;
    Label1: 
            printf("The value of i =%d\n",i);
            i++;
            if(i<105)
            goto Label1;
        }
    }
    
    void function3(int x, int y);
    
    int main(void) 
    {
        function1();
        function2();
        return 0;
    }
    

    在示例中,

    • 'function1()'具有'程序范围'。
    • 'function2()'有'文件范围'。
    • 'Label1'具有'功能范围'。 (标签名称在功能中必须是唯一的。'标签'是唯一具有功能范围的标识符。
    • 变量'i'具有'Block Scope'。
    • 变量'x'和'y'具有'原型范围'。函数参数列表中不能有两个名称为“x”或“y”的变量。

    上例中的变量i具有块范围。如果控件超出范围(生命结束),则变量消失。您无法访问该变量。

    所以C提供了动态内存构造来访问这种场景中的内存。 例如:

    int* function(void)
    {
        int *ptr  = malloc(sizeof(int));
        *ptr = 5;
        return ptr;
    }
    
    int main(void)
    {
        printf("%d", function());
        return 0;
    }
    

    即使变量printf超出范围,ptr仍会打印该值,但ptr指向的内存仍然存在(有生命)。

    另请阅读https://stackoverflow.com/a/18479996/1814023