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

为什么我们需要calloc(或malloc)?,c,dynamic-allocation,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 si

在我整个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.
这有什么用


我在谷歌上搜索了一下,但没有用,所以请原谅我-很不幸*在谷歌中是一个通配符,因此很难找到相关的结果。

在当前上下文中声明的变量在上下文结束时结束其生命周期

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

比如说,

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
函数显式返回池之前保持有效。不将其返回池将导致内存泄漏。

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

当涉及到变量分配时,您可以这样做:

  • 静态地在堆栈上,只需:
    inta=10
    。这些变量很可能与使用它们的一些代码一起定义在堆栈上(这就是为什么在没有正确检查Boudardries的情况下写入堆栈上声明的数组可能会很危险。您可能会覆盖代码)。变量还有一个作用域:函数作用域、全局作用域和其他作用域(例如if-else的if分支)。它们使用起来很快,但是它们或多或少。。。静电,它们有一个很大的优势,你不需要清洁它们。它们由应用程序自动清理。然而,他们有一个很大的劣势。堆栈空间比堆空间更有限。因此,您只能使用大小适中的变量(不要照字面意思理解,而是研究一下您的操作系统允许的变量。64KB对每个人来说都是不够的:)
  • 使用
    calloc()
    或其他一些内存分配函数在堆上动态执行。这些变量在称为堆或动态内存的区域中声明。这些变量将一直保留在那里,直到使用它们的应用程序退出(在这种情况下,(现代)操作系统通常会将内存回收给自己),或者使用
    free()
    ,它们是
    free
    d。您应该始终释放内存以避免内存泄漏。动态内存的优点是(在现代操作系统上)可寻址内存比分配给堆栈空间的大小大得多,因此您可以拥有更多、更大、更大的结构和阵列

  • 作用域是代码中可以访问变量的区域或部分。可能有

  • 文件范围
  • 功能范围
  • 块范围
  • 项目范围
  • 原型范围
  • 范例

    #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;
    }
    
    printf
    仍将打印值,即使变量
    ptr
    超出范围,但
    ptr
    指向的内存仍然存在(具有寿命)


    另外读取

    区别在于静态分配(在堆栈上)和动态分配(在堆上)读取此项:另一个原因是您并不总是事先知道需要多少数据<代码>双d[1000]是非常浪费的,如果您需要超过1000个元素,那么它是危险的。如果您可以在运行时确定需要多少内存,就可以提高内存使用效率。如果学习C,请帮自己一个忙并实现。许多人坚持这样做,但这是一种反模式;问题不是为什么要使用
    calloc()
    而不是其他一些动态分配,而是为什么要使用动态分配。
    int* function(void)
    {
        int *ptr  = malloc(sizeof(int));
        *ptr = 5;
        return ptr;
    }
    
    int main(void)
    {
        printf("%d", function());
        return 0;
    }