2014-05-13 156 views
1

在我整个CS生涯中忽略了C后,我决定给它看一看!为什么我们需要calloc(或malloc)?

当初始化变量,我们可以有:

int b = 0; 

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

b = 2; 

更新如果需要的话。

所以,原谅我这个可笑的“小白”的问题,但为什么我们需要一个像电话:

double *b = (double *) calloc(n, sizeof(double)); 
初始化变量将已经分配的空间,它的时候

为什么我们不只是做

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

什么用的呢?

我试过谷歌搜索这没有用,所以请原谅我 - 很遗憾*谷歌是一个通配符,所以相关的结果很难找到。

+0

不同的是静态分配(堆栈)和动态分配(在HEAP) –

+1

阅读这一个:http://stackoverflow.com/questions/8385322/difference-between-static-memory-分配和动态内存分配 – pablochan

+1

另外一个原因是你并不总是事先知道你需要多少数据。'double d [1000];'如果你只需要几个元素是非常浪费的,如果你需要超过1000个元素是很危险的。如果你可以在运行时确定你需要多少,你可以使内存使用更有效率。 – mah

回答

2

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

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

例如,

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功能池。不将它返回到池会造成内存泄漏。

0

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

+2

方式无关紧要;问题不在于为什么要使用'calloc()'而不是其他一些动态分配,这就是为什么要使用动态分配。 – mah

0

当谈到关于可变分配,你可以不喜欢它:

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

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

  1. 文件范围
  2. 功能范围
  3. 块作用域
  4. 计划范围
  5. 原型范围

#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; 
} 

在电子xample,

  • 'function1()'有'程序范围'。
  • 'function2()'有'文件范围'。
  • 'Label1'有'功能范围'。 (标签名称必须在功能范围内是唯一的。“标签”是具有函数作用域的唯一标识符。
  • 变量“I”具有“块范围”。
  • 变量“x”和“Y”具有“原型范围”不能有两个变量的名称的‘x’或‘在函数参数列表Y’。

在上述例子中所述的可变i具有块范围。如果控制超出范围(生活你不能访问该变量

所以C提供了动态内存构造以符合acc在这些场景中记忆这些记忆。 例如:

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