Question

After ignoring C for my entire CS career I have decided to give it a look!

When initialising variables, we can have :

int b = 0;

This initialises b, allocates memory for it, and we can later update it with

b = 2;

if needs be.

So, and forgive me for this ridiculously "noob" question but why do we need calls like :

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

when initialising the variable would allocate the space for it already?

Why can we not just do

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

What is the use of this?

I have tried Googling this to no avail so please forgive me - ufortunately * in Google is a wildcard and so relevant results are hard to find.

Was it helpful?

Solution

Variables declared in the current context end their lifetime at the end of the context.

Allocating memory gives you space to store longer-lived variables.

For example,

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

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

will try to access a variable that no longer exists, because its lifetime is the foo function.

C and C++ do not keep track of objects. A pointer only points to the object, but does not extend object lifetime, so it is entirely possible for a pointer to be invalid even if it is not NULL.

However, this is valid:

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

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

This will allocate memory for a double, and return the pointer to the memory, which remains valid until explicitly returned to the pool using the free function. Not returning it to the pool will create a memory leak.

OTHER TIPS

Unless I'm totally mistaken, in C, calloc or malloc are the only possibilities to implement dynamic data structures.

When it comes about variable allocation you can do it like:

  1. statically on the stack, simply: int a = 10. These variables are defined on the stack most possibly together with some of the code using them (this is why it can be dangerous to write in an array declared on the stack without proper checking the boudadries. You might overwrite code). The variables also have a scope: function scope, global scope, and other scopes (such as the if-branch of an if-else). They are fast to use, however they are more or less ... static, and they have the big advantage that you don't need to clean them. They are automatically cleaned by the application. However they have a great disadvantage. Stack space is more limited than heap space. So you can use only modest sized variables (Don't take it literally, instead do some research what is allowed by your OS . 64KB is not enough to everyone :) ).
  2. Dynamically on the heap, using either calloc() or some other memory allocation function. These variables are declared in an area known as the heap, or dynamic memory. These variables will stay there either until the application using them exits (in this case the (modern) OS usually reclaims the memory to itself), or they are freed using free(). You always should free the memory to avoid memory leaks. Dynamic memory has the advantage that (on a modern OS) the addressable memory is much bigger than the size allocated to stack space so you can have more, bigger, greater structures and arrays.

Scope is the region or section of the code where a variable can be accessed. There can be

  1. File Scope
  2. Function Scope
  3. Block Scope
  4. Program Scope
  5. Prototype Scope

Example

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

In the example,

  • ‘function1()’ has ‘Program Scope’.
  • ‘function2()’ has ‘File Scope’.
  • ‘Label1’ has ‘Function Scope’. (Label names must be unique within the functions. ‘Label’ is the only identifier that has function scope.
  • Variable ‘i’ has ‘Block Scope’.
  • Variable ‘x’ and ‘y’ has ‘Prototype Scope’. There cannot be two variables with the name ‘x’ or ‘y’ in the function parameter list.

The variable i in the above example have the block scope. If the control goes out of scope (life ends), then the variable is gone. You can not access the variable.

So C provides dynamic memory constructs to access the memory in these kind of scenarios. For example:

int* function(void)
{
    int *ptr  = malloc(sizeof(int));
    *ptr = 5;
    return ptr;
}

int main(void)
{
    printf("%d", function());
    return 0;
}

the printf would still print the value even the variable ptr is out of scope but the memory pointed by ptr still exists (has life).

Also read https://stackoverflow.com/a/18479996/1814023

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top