Arrays, pointers, and memory management toy example question in C - c

I was playing around with C memory and pointers, and I had some questions:
int* foo(){
int a[100] = ...;
int* b = malloc(100 * sizeof(int));
... do something ...
return b
}
Is the memory consumed by a freed immediately after exiting the function?
Would changing the definition to int b [100]; be equivalent?

This declaration
int a[100] = ...;
declares a local object with the automatic storage duration. So after exiting the function the array will not be alive and its memory can be used for other purposes.
Returning from the function the array
int b [100];
like
return b;
makes the returned pointer invalid because as it has been said above the array b will not be alive after exiting the function
As for the dynamically allocated memory
int* b = malloc(100 * sizeof(int));
then it will be freed only when you will implicitly call the function free or when the process will stop its execution.
You could return the array if it had static storage duration. For example
static int b[100];

Remember that a is scoped to the function and as soon as the function exits it falls out of scope meaning any references to it, like pointers, are invalidated. Understanding scope is really important, so be sure to learn more about this before you end up introducing undefined behaviour into your programs inadvertently.
Changing b to be the same as a would subject it to the same problems. malloc() is used to dynamically allocate something and it will be valid until explicitly released with free().
Don't forget that allocating memory comes with the responsibility of releasing it. You need to have a plan to deal with that allocation.

Related

Returning an array of variable size in c from a function

So i want to return an array of a size n (variable) which my function has as input. I know that in order to return arrays in C I have to define them static, but the problem is that n is a variable and thus I get an error. I thought of actually using malloc/calloc but then I won't be able to free them after the function returns the array. Please take note that I'm not allowed to change anything on main(). Are there any other alternatives which I could use? Thanks in advance.
float *Arr( int *a , int n ){
static float b[ n ];
return b
}
Got to point out that the function will only be called Once,I saw the solution you posted but i noticed you aren't freeing the allocated memory,is it not of much importance when the malloc is called inside a function?
The important thing to notice here is that this syntax:
float arr[n];
Allocates an array on the stack of the current function. In other words, that array is a local variable. Any local variable becomes invalid after the function returns, and therefore returning the array directly is undefined behavior. It will most likely cause a crash when trying to access the array from outside the function, if not anything worse.
In addition to that, declaring a variable-length array as static is invalid in any case.
If you want to write a function which creates and returns any kind of array (dynamically sized or not), the only option you have is to use dynamic allocation through malloc() and then return a pointer to the array (technically there's also alloca() to make dynamic stack allocations, but I would avoid it as it can easily break your program if the allocation is too large).
Here's an example of correct code:
float *create_array(size_t n_elements){
float *arr = malloc(sizeof(float) * n_elements);
if (arr == NULL) {
// Memory could not be allocated, handle the error appropriately.
}
return arr;
}
In this case, malloc() is reserving memory outside of the local stack of the function, in the heap. The result is a pointer that can be freely returned and passed around without any problem, since that area of memory keeps being valid after the function returns (until it is released). When you're done working with the data, you can release the allocated memory by calling free():
float *arr = create_array(100);
// ...
free(arr);
If you don't have a way to release the memory through free() after using malloc(), that's a problem in the long run, but in general, it is not a strict requirement: if your array is always needed, from its creation until the exit of the program, then there's no need to explicitly free() it, since memory is automatically released when the program terminates.
If your function needs to be called more than once or needs to create significantly sized arrays that are only useful in part of the program and should therefore be discarded when no longer in use, then I'm afraid there's no good way of doing it. You should use free() in that case.
To answer your question precisely:
Please take note that I'm not allowed to change anything on main(). Are there any other alternatives which I could use?
No, there are no other better alternatives. The only correct approach here is to dynamically allocate the array through malloc(). The fact that you cannot free it afterwards is a different kind of problem.
So i want to return an array of a size n(variable) which my function
has as input,
You can't, because C functions cannot return arrays at all. They can, and some do, return pointers, however, as your function is declared to do. Such a pointer may point to an element of an array.
i know that in order to return arrays in c i have to
define them static,
As long as I am being pedantic, the problem is to do with the lifetime of the object to which the returned pointer points. If it is an element of an automatically-allocated array, then it, along with the rest of the array, ceases to exist when the function returns. The caller must not try to dereference such a pointer.
The two other alternatives are
static allocation, which you get by declaring the variable static or by declaring it at file scope, and
dynamic allocation, which you get by reserving memory via malloc(), calloc(), or a related function.
Statically allocated objects exist for the entire lifetime of the program, and dynamically allocated ones exist until deallocated.
but problem is that n is a variable and thus i get
an error.
Yes, because variable-length arrays must be automatically allocated. Static objects exist for the whole run of the program, so the compiler needs to reserve space for them at compile time.
I thought of actually using malloc/calloc but then i won't be
able to free them after the function returns the array.
That's correct, but dynamic allocation is still probably the best solution. It is not unreasonable for a called function to return a pointer to an allocated object, thus putting the responsibility on its caller to free that object. Ordinarily, that would be a well-documented characteristic of the function, so that its callers know that such responsibility comes with calling the function.
Moreover, although it's a bit untidy, if your function is to be called only once then it may be acceptable to just allow the program to terminate without freeing the array. The host operating system can generally be relied upon to clean up the mess.
Please take
note that im not allowed to change anything on main(),are there any
other alternatives which i could use?
If you have or can impose a bound on the maximum value of n then you can declare a static array of that maximum size or longer, and return a pointer to that. The caller is receiving a pointer, remember, not an array, so it can't tell how long the pointed-to array actually is. All it knows is that the function promises n accessible elements.
Note well that there is a crucial difference between the dynamic allocation and static allocation alternatives: in the latter case, the function returns a pointer to the same array on every call. This is not inherently wrong, but it can be problematic. If implemented, it is a characteristic of the function that should be both intentional and well-documented.
If want an array of n floats where n is dynamic, you can either create a
variadic-length array (VLA):
void some_function(...)
{
//...
float b[ n ]; //allocate b on the stack
//...
}
in which case there would be no function call for the allocation, or you can allocate it dynamically, e.g., with malloc or calloc, and then free it after you're done with it.
float *b = malloc(sizeof(*b)*n);
A dynamic (malloc/calloc) allocation may be wrapped in a function that returns a pointer to the allocated memory (the wrapper may do some initializations on the allocated memory after the memory has been successfully allocated). A VLA allocation may not, because a VLA ends its lifetime at the end of its nearest enclosing block (C11 Standard - 6.2.4 Storage durations of objects(p7)).
If you do end up wrapping a malloc/calloc call in a "constructor" function like your float *Arr(void), then you obviously should not free the to-be-returned allocated memory inside Arr–Arr's caller would be responsible for freeing the result (unless it passed the responsibility over to some other part of the program):
float *Arr( int n, ...
/*some params to maybe initialize the array with ?*/ )
{
float *r; if (!(r=malloc(sizeof(*r)*n)) return NULL;
//...
//do some initializations on r
//...
return r; //the caller should free it
}
you could use malloc to reserve memory for your n sized array
Like this:
#include <stdlib.h>
#include <stdio.h>
float * arr(int * a, int n ) {
float *fp = malloc ( (size_t) sizeof(float)*n);
if (!fp) printf("Oh no! Run out of memory\n");
return fp;
}
int main () {
int i;
float * fpp = arr(&i,200);
printf("the float array is located at %p in memory\n", fpp);
return(0);
}
It seems like what you want to do is:
have a function that provides (space for) an array with a variable number of elements,
that the caller is not responsible for freeing,
that there only needs to be one instance of at a time.
In this case, instead of attempting to define a static array, you can use a static pointer to manage memory allocated and freed with realloc as needed to adjust the size, as shown in the code below. This will leave one instance in existence at all times after the first call, but so would a static array.
This might not be a good design (it depends on circumstances not stated in the question), but it seems to match what was requested.
#include <stdio.h>
#include <stdlib.h>
float *Arr(int *a , int n)
{
// Keep a static pointer to memory, with no memory allocated initially.
static float *b = NULL;
/* When we want n elements, use realloc to release the old memory, if any,
and allocate new memory.
*/
float *t = realloc(b, n * sizeof *t);
// Fail if the memory allocation failed.
if (!t)
{
fprintf(stderr, "Error, failed to allocate memory in Arr.\n");
exit(EXIT_FAILURE);
}
// Return the new memory.
return b;
}

Differences in memory allocations [duplicate]

This question already has answers here:
Difference between static memory allocation and dynamic memory allocation
(7 answers)
Closed 5 years ago.
I was wondering if someone could explain the differences between the memory allocation for ai and *pai
int ai[10];
int *pai = (int * ) calloc (10, sizeof(int));
I understand the second one is dynamically allocated but im struggling to explain why.
Let's see what is being specified in standard (difference wise)
From 7.22.3.1 (Under Memory management functions)
... The lifetime of an allocated object extends from the allocation
until the deallocation.
So yes, this is for dynamically allocated memory. Their lifetime is different from that of local variables. By calling free they are deallocated. Until then they will be alive. Doesn't depend on the life time of the scope on which they are created.
The first one is having automatic storage duration. This is the primary difference. So in the functions scope where it is declared, when it ends then it's lifetime will be over.
Also some people say that there is a heap and stack - but (un)fortunately C standard doesn't mention it. It is completely implementation of the features expected by the C standard. The implementation can be anything. The differences presented is least bothered about those kind of stuff.
As a conceptual redpill (taken from movie Matrix) pai is of automatic storage duration but the address of the memory it contains is not. The variable pai will be lost when the function where it is defined is executed. But the memory it points to, doesn't.
Well why is it called dynamic allocation?
Know one thing - when in programming we say dynamic in the context of language - it means we are doing something in runtime. Same here, we are allocating some memory when in run time by calling functions like malloc,calloc etc. That's why dynamic allocation.
In the first line, you create a variable of an array type, but the symbol ai is a constant pointer to this variable.
in the second line, you create a pointer type variable. then you allocate an array dynamically with calloc() and you puts it's address in the pointer.
The array ai is allocated on the stack, it implicitly goes out of scope, when the end of the function is reached. The pointer pai points to a memory location, which can be an array or a single element of the type pointed to, the memory is allocated on the heap and must be freed later. The second can be passed back to the function-caller on the end of the function and can even be resized with realloc (realloc does not clear the new memory like calloc does, malloc is like calloc without zeroing out the new memory). The first is for fast array computation and should be in the cache most of the time. The second is for unknown lenght of arrays, when the function is called. When the size is known, many programmers tend to define an array in the caller and pass it to the function, which modifies it. The array is implicitly converted to a pointer when calling the function.
Some library implementations store a pointer to an array in the global section, which can be reallocated. Or they have a fixed length array in global space. These variables are recommended to be thread_local. The user does not have to care about the memorymanagement of the variable of the other library.
library.h
const char* getResourceString(int id);
library.c
thread_local char* string_buf = NULL;
const char* getResourceString(int id) {
int i = getResourceSize(id);
string_buf = realloc(string_buf, i);
// fill the memory
return string_buffer;
};
These are quite different operations:
int ai[10];
declares an array object of 10 ints. If it is declared inside a block, it will have automatic storage duration, meaning that it will vanish at block end (both identifier and data). If it is declared outside any block (at file level) it will have static storage duration and will exist throughout all program.
int *pai = calloc (10, sizeof(int)); // DON'T CAST MALLOC IN C
declares a pointer to an allocated zone of memory that can contains ten integers. You can use pai as a pointer to the first element of an array and do pointer arithmetics on it. But sizeof(pai) is sizeof(int *). The array will have dynamic storage duration meaning that its life will end:
if the allocated block of memory is freed
if it is reused to store other objects
double * pd = pai;
for (int i=1; i<5; i++) { // assuming sizeof(double) == 2 * sizeof(int) here
pd[i] = i; // the allocated memory now contains 5 double
}
So in both case you can use the identifier as pointing to an array of 10 integers, but first one is an integer array object while second one is just a pointer to a block of dynamic memory (memory with no declared type that can take the type of an object that will be copied/created there) .
Gerenally speaking, automatically allocated objects will be on the stack, while dynamically allocated objects will be on the heap. Although this distinction is implementation (not standard) dependent, stack and heap are the most commonly used way to manage memory in C programs. They are basically two distinct regions of memory, the first is dedicated to automatic allocations and the second is dedicated to dynamic allocations. So when you call a function (say, the main function) all the objects declared in the scope of this function will be stacked (automatically allocated in the stack). If some dynamic allocation happens in this function, the memory will be allocated in the heap so that all pointers to this area will be pointing to objects outside the stack. When your function returns, all objects in the stack are also automatically unstacked and virtually don't exist anymore. But all objects in the heap will exist until you deallocate them (or they will be forcefully deallocated by the OS when the program ends). Arrays are structures that can be allocated automatically or dynamically. See this example:
int * automaticFactor() //wrong, see below
{
int x[10];
return &x[0];
}
int * dynamicFactor()
{
int * y = (int *) malloc(sizeof(int) * 10);
return &y[0];
}
int main()
{
//this will not work because &x[0] points to the stack
//and that area will be unstacked after the function return
int * n = automaticFactor();
//this will work because &y[0] points to the heap
//and that area will be in the heap until manual deallocation
int * m = dynamicFactor();
return 0;
}
Note that the pointers themselves are in the stack. What is in the heap is the area they are pointing to. So when you declare a pointer inside a function (such as the y of the example), it will also be unstacked at the end of the function. But since its value (i.e. the address of the allocated area) was returned to a pointer outside the function (i.e. to m), you will not lose track of the area allocated in the heap by the function.

Dynamically Allocated Array vs. Automating Declared Array with Global Scope (C language)

What is the difference between declaring an array "dynamically",
[ie. using realloc() or malloc(), etc... ]
vs
declaring an array within main() with Global scope?,
eg.
int main()
{
int array[10];
return 0;
}
I am learning, and at the moment it feels that there is not much differnce between
declaring a variable (array, whatever) -with Global scope,
when compared to a
dynamically allocated variable (array, whatever) -AND never calling free() on it AND allowing it to be 'destoryed' when the program ends'
What are the consequences of either option?
EDIT
Thank you for your responses.
Global scope should have been 'local scope' -local to main()
When you declare an array like int arr[10] in a function, the space for the array is allocated on the stack. The memory will be freed when your function exits.
When you declare an array or any other data structure using malloc() or realloc(), you allocated the space on the heap and the memory will only be freed afer the program exits. So when the program is running, you are responsible for freeing it using free() after you no longer want to use it. If you don't free it and make your array pointer point to something else, you will create a memory leak. However, your computer will always be able to retrieve all the program's used memory after the program ends because of virtual memory.
As kaylum said in comment below your question, the array in your second example does not have global scope. Its scope is limited to main(), and it is inaccessible in other scopes unless main() explicitly makes it available (e.g. passes it by argument to another function).
Dynamic memory allocation means that the programmer explicitly allocates memory when needed, and explicitly releases it when no longer needed. Because of that, the amount of memory allocated can be determined at run time (e.g. calculated from user input). Also, if the programmer forgets to release the memory, or reallocates it inappropriately, memory can be leaked (still allocated by the program, but not accessible by the program). For example;
/* within a function */
char *p = malloc(100);
p = malloc(200);
free(p);
leaks 100 bytes, every time this code is executed, because the result of the first malloc() call is never released, and it is then inaccessible to the program because its value is not stored anywhere.
Your second example is actually an array of automatic storage duration. As far as your program is concerned, it only exists until the end of the scope in which it is created. In your case, as main() returns, the array will cease to exist.
An example of an array with global scope is
int array[10];
void f() {array[0] = 42;}
int main()
{
array[0] = 10;
f();
/* array[0] will be 42 here */
}
The difference is that this array exists and is accessible to every function that has visibility of the declaration, within the same compilation unit.
One other important difference is that global arrays are (usually) zero initialised - a global array of int will have all elements zero. A dynamically allocated array will not have elements initialised (unless created with calloc(), which does initialise to zero). Similarly, an automatic array will not have elements initialised. It is undefined behaviour to access the value of something (including an array element) that is uninitialised.
So
#include <stdio.h>
int array[10];
int main()
{
int *array2;
int array3[10];
array2 = malloc(10*sizeof(*array2));
printf("%d\n", array[0]); /* okay - will print 0 */
printf("%d\n", array2[0]); /* undefined behaviour. array2[0] is uninitialised */
printf("%d\n", array3[0]); /* undefined behaviour. array3[0] uninitialised */
return 0;
}
Obviously the way to avoid undefined behaviour is to initialise array elements to something valid before trying to access their value (e.g. printing them out, in the example above).

Not sure whether or not to malloc memory for a struct

Suppose I have the following C code:
#include <stdio.h>
#include <stdlib.h>
#define NUM_PEOPLE 24
typedef struct {
char **name;
int age;
} person_t;
void get_person_info(person_t *person);
int main(int argc, char **argv) {
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t new_person;
get_person_info(&new_person);
}
return 0;
}
where get_person_info() just fills out the person_t struct to which a pointer is passed in. Is it necessary to malloc() memory for new_person within main()? That is, should the line
person_t new_person;
instead be
person_t *new_person = (person_t *) malloc(sizeof(person_t));
and then change get_person_info() to accept a person_t ** instead of a person_t *?
Sorry if this question is confusing -- I'm not sure whether or not this is a case where it is necessary to reserve memory, given that a pointer to that memory is passed into get_person_info() to avoid causing a segmentation fault.
Both are correct, it depends on where you want to use the person_info.
Allocating on the stack :
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t new_person;
get_person_info(&new_person);
}
Creates a person_t object on the stack and fills the new_person object with data, because the loop only does that, the object goes out of scope on the next loop iteration and the data is lost.
Using malloc :
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t *new_person = malloc(sizeof(person_t));
get_person_info(new_person);
}
Creates a person_t object on the heap and fills it with data, because its allocated on the heap the new_person object will outlive the loop scope which currently means that you're leaking memory because you have no pointer pointing at the data of the person_t object of the previous loop cycle.
Both ways are correct !!
person_t *new_person = (person_t *) malloc(sizeof(person_t));
and then change get_person_info() to accept a person_t ** instead of a person_t *?
you don't need to change parameter of function -void get_person_infperson_t *person);.Just pass pointer to it in main like this -
get_person_info(new_person);
But in previous way without allocating memory , you won't be able to use it outside the block it is defined in whereas if your program depend on its life you can allocate memory to it on heap.
In your code you posted new_person is used inside loop only so if you don't intend to use to outside loop you probably won't need dynamic allocation .
But if you want to use it outside loop also you should use dynamic allocation. But don't forget to free it.
Not sure whether or not to malloc memory for a struct?
The short answer is: no need to do it in your case. If you want to use your object outside the forloop you could do it by dynamically allocated memory, namely:
person_t *new_person = malloc(sizeof(person_t));
and then call it with:
get_person_info(new_person);
In you example, the object is used within the loop, thus there is no need to do it.
Note:
when you use dynamically allocated memory you should always free it, at the end to avoid memory leaks.
Edit:
As pointed out by #Johann Gerell, after removing the redundancy of the casting of the return type of malloc, in C, the allocation would look like:
person_t *new_person = malloc(sizeof(person_t));
malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. The use of casting is required in C++ due to the strong type system, whereas this is not the case in C.
Your confusion stems from not understanding object storage duration and pointers well. Let's see each one separately to get some clarity.
Storage Duration
An object can have automatic or dynamic storage duration.
Automatic
Automatic, as the name says, would be managed by the compiler for you. You just define a variable, use it and when it goes out of scope the object is destroyed automatically for you. A simple example:
if (flag) {
int i = 0;
/* some calc. involving i */
}
// i is dead here; it cannot be accessed and its storage is reclaimed
When the control enters the if's scope, memory large enough to hold an int will be allocated automatically and assigned the value 0. Once your use of i is over, when the control exits the scope, the name i goes out of scope and thus will no longer be accessible by the program and also its storage area allocated automatically for you would be reclaimed.
Dynamic
Lets say you want to have objects dynamically allocated i.e. you want to manage the storage and thereby the lifetime of the object without the scope or the compiler coming in your way, then you'd go on by requesting storage space from the platform using malloc
malloc(sizeof(int));
Notice that we're not assigning the return value of malloc to any pointer as you're used to seeing. We'll get to pointers in a bit, lets finish dynamic objects now. Here, space large enough to hold an int is handed over to you by malloc. It's up to you to free it when you're done with it. Thus the lifetime of this unnamed int object is in your hands and would live beyond the scope of the code that created it. It would end only when you explicitly call free. Without a matching free call getting called, you'd have the infamous memory leak.
Pointers
A pointer is just what its name says - an object that can refer to another object. A pointer is never what it is pointing at (pointee). A pointer is an object and its pointee is another separate, independent object. You may make a pointer point to another named object, unnamed object, or nothing (NULL).
int i = 0;
int *ptr1 = &i; // ptr1 points to the automatic int object i
int *ptr2 = malloc(sizeof(int)); // ptr2 points to some unnamed int object
int *ptr3 = NULL; // ptr3 points to nothing
Thus the reason most people confuse pointers for dynamically allocated pointees comes from this: the pointee, here, doesn't have a name and hence they're referred to always via their pointers; some people mistake one for the other.
Function Interface
The function taking a pointer is appropriate here, since from the caller's viewpoint it's a flexible function: it can take both automatic and dynamic objects. I can create an automatic variable and pass it in, or I can pass a dynamic variable too:
void get_person_info(person_t *person);
person_t o { };
get_person_info(&a);
person_t *p = malloc(sizeof(person_t));
get_person_info(p);
free(p);
Is it necessary to malloc() memory for new_person within main()?
No. You can define an automatic variable and pass it to the function. In fact it's recommended that you try to minimize your usage of dynamic objects and prefer automatic objects since
It minimizes the chances of memory leaks in your code. Even seasoned programmers miss calling the matching free to a malloc thereby introducing a memory leak.
Dynamic object allocation/deallocation is far slower than automatic variable allocation/deallocation.
A lot of dynamic allocation deallocation causes memory fragmentation.
However, automatic variables are generally allocated in the stack and thus the upper limit on the number and size on how much you can create on the stack is relatively lower than what you can allocate dynamically (generally from the heap).
change get_person_info() to accept a person_t ** instead of a person_t *?
No, if you did so, the option of passing automatic variables would still be possible but cumbersome:
void foo(int **o);
int i = 0;
int *p = &i; // p is redundant
foo(&p);
int *p = malloc(sizeof(int));
foo(&p);
As opposed the simpler
void bar(int *o);
int i = 0;
bar(&i);
int *p = malloc(sizeof(int));
bar(p);

Why do we need calloc (or malloc)?

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.
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.
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:
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 :) ).
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
File Scope
Function Scope
Block Scope
Program Scope
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

Resources