Am I correct in thinking that:
char *buff[500];
... creates a stack variable, and:
char *buff = (char *)malloc(500);
... creates a heap variable?
If that's correct, when and why would you use heap variables over stack variables and vice versa. I understand the stack is faster is there anything else.
One last question, is the main function a stack frame on the stack?
Yes, first one creates an array of char pointers in the stack, about 500*4 bytes and second one allocates 500 chars in the heap and points a stack char ptr to them.
Allocating in the stack is easy and fast, but stack is limited, heap is slower but much bigger. Apart from that, stack allocated values are "deleted" once you leave the scope, so it is very good for small local values like primitive variables.
If you allocate too much in the stack you might run out of stack and die, main as all the functions you execute has a stack frame in the stack and all the local variables to the function are stored there, so going too deep into function calling might get you into a stackoverflow as well.
In general is a good rule of thumb to allocate anything that you use often and is bigger than a hundred bytes in the heap, and small variables and pointers in the stack.
Seeing that you wrote
char *buff = (char *)malloc(500);
you probably meant
char buff[500]; instead of
char* buff[500];
in your first example (so you have a char-array, not an array of pointers to chars)
Yes, "allocation" on the stack is faster because you just increase a pointer stored in the ESP register.
You need heap-variables if you want:
1) more memory than fits in the stack (generally much earlier)
2) pass memory that was allocated by a called function to the calling function.
Your buffs are not equivalent.
The first one (char *buff[500]) is an array of 500 pointers; the 2nd one (char *buff = (char *)malloc(500)) is a pointer.
The pointer (on the stack) points to 500 bytes of memory (if the malloc call succeeded) on the heap.
The array of pointers is on the stack. Its pointers are not initialized.
Unless using C99, using the stack the size of your array must be known at compile-time. That means you cannot do:
int size = 3; // somewhere, possibly from user input
char *buff[size];
But using "the heap" (dynamic allocation), you can provide any dimensions you like. That's because the memory allocation is performed at run-time, rather than hardcoded into the executable.
The C standard contains neither the words heap nor stack. What we have here instead are two storage durations (of 4 in total): automatic and allocated:
char buff[500]; // note the missing * to match the malloc example
within a function declares the object buff as an array of char and having automatic storage duration. The object will cease to be when the block where the object was declared, is exited.
char *buff = malloc(500); // no cast necessary; this is C
will declare buff as a pointer to char. malloc will reserve 500 continuous bytes and return a pointer to it. The returned 500-byte object will exist until it is explicitly freed with a call to free. The object is said to have allocated storage duration.
That's all the C standard says. It doesn't specify that the char buff[500] needs to be allocated from a "stack", or that there needs to be a stack. It doesn't specify that the malloc needs to use some "heap". On the contrary, a compiler might internally implement the char buff[500] like
{
char *buff = malloc(500);
free(buff);
}
Or it can deduce that the allocated memory is not used, or that it is only used once, and use a stack-based allocation instead of actually calling malloc.
In practice, most current compilers and environments will use a memory layout called stack for automatic variables, and the objects with allocated storage duration are said to come from "heap" which is a metaphor for the unorganized mess that it is compared to the orderly stack, but it is not something that has to be so.
Heap variables can be created dynamically, ie you can ask a size to your user and malloc a new variable with this size.
The size of a stack variable must be known at compile time.
Like you said, stack variable are faster allocated and accessed. So i'll recommend using them every time you know the size at compile time. Otherwise you don't have the choice, you must use malloc()
This is indeed a variable allocated on the stack:
char buff[500]; // You had a typo here?
and this is on the heap:
char *buff = (char *)malloc(500);
Why would you use one vs the other?
In char *buff[500], the 500 needs to be a compile-time constant. You can't use it if 500 is computed at runtime.
On the other hand, stack allocations are instantaneous while heap allocations take time (thus they incur a runtime performance cost).
Space on the stack is limited by the thread's stack size (typically 1MB before you get a stack overflow), while there's much more available on the heap.
If you allocate an array on the stack big enough to take up more than 2 pages of virtual memory as managed by the OS, and access the end of the array before doing anything else, there's the possibility of getting a protection fault (this depends on the OS)
Finally: every function called has a frame on the stack. The main function is no different. It isn't even any more special than the other functions in your program, since when your program starts running the first code that runs is inside the C runtime environment. After the runtime is ready to begin execution of your own code, it calls main just as you would call any other function.
Those two aren't equivalent. The first is an array of size 500 (on the stack) with pointers to characters. The second is a pointer to a memory chunk of 500 which can be used with the indexing operator.
char buff[500];
char *buff = (char *)malloc(sizeof(char)*500);
Stack variables should be preferred because they require no deallocation. Heap variables allow passing of data between scopes as well as dynamic allocation.
Related
I was curious with this:
What is the diference between:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
and:
char Buffer[MAX_BUF];
Case 1: In
char Buffer[MAX_BUF];
Buffer is an array of size MAX_BUF. The allocation technique is called VLA.
Case 2: In
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
Buffer is a pointer which is allocated a memory of size MAX_BUF which is 1000.
and, an array is not the same as a pointer, and C-FAQ has a Very Good collection detailing the reasons.
The major difference, in terms of usability and behaviour are:
(1) is on stack, usually Note, while (2) is on heap, always.
(1) has fixed size once allocated, (2) can be resized.
(1) is allocated when the enclosing function is called and has the block scope OTOH, (2) is allocated memory dynamically, at runtime and the returned memory has a lifetime which extends from the allocation until the deallocation.
(1) allocated memory need not be managed by programmer, while in (2) all malloc()d memory should be free()d. [Courtesy: Giorgi]
Note: Wiki
For example, the GNU C Compiler allocates memory for VLAs on the stack.
I will add a bit info in terms of memory management, in addition to what others said.
1) The main difference is here:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
You need to manage the allocated memory manually, e.g., free Buffer when you are done using it. Forgetting to free it (or freeing it twice) may lead to trouble.
2) With the second case:
char Buffer[MAX_BUF];
You don't need to free anything. It will get destroyed automatically. Hence you avoid the task of handling the memory - which is good.
You should try to evaluate always which approach you need.
Some points.
Since second is allocated on stack, the first approach is taken also when large array needs to be created - since more memory is usually available on the heap.
Also if you create array using second approach for example in the method, the life time of the object will be that method - you will not be able to use that array outside that method. Whereas with dynamic allocation that is not the case.
char* Buffer = malloc(MAX_BUF);
creates a char pointer Buffer, dynamically allocates MAX_BUF bytes of memory via the malloc and makes Buffer point to the start of the allocated space. This memory is allocated on the heap.
char Buffer[MAX_BUF];
creates an array Buffer of size MAX_BUF which can hold a maximum of MAX_BUF characters. Note that you are creating a Variable Length Array (a feature introduced in C99) since MAX_BUF is a variable. This array may be created on the stack.
The most notable difference is scope. The VLA array will only be valid inside the scope where it is declared, while a dynamic array will be available everywhere in the program until you call free().
In practice, VLAs may be faster than dynamic memory, in case the compiler use stack allocation for the VLA. It is however not specified by the C standard where a VLA is allocated.
(A compiler could in theory allocate a VLA on the heap, but then the compiler would also be responsible for the clean-up. I don't think any such solutions exist. Every compiler I've used always declare VLAs on the stack.)
This means that VLAs are unsuitable to hold large amounts of data: you would risk stack overflow. This is not a concern when you are using dynamic memory however.
VLAs don't have the same portability as dynamic arrays, since awfully old compilers don't support VLAs. In theory, new C11 compilers don't have to suport VLAs either, though at this point I know of no compiler has been stupid enough to drop that support.
Comparison/summary:
VLAs should be used when there are small amounts of local data, because they have fast allocation time and automatic clean-up.
Dynamic arrays should be used when there are large amounts of data, to prevent stack overflow.
Dynamic arrays should be used when the data needs to persist after the execution of a function and be available elsewhere in the program.
Dynamic arrays should be used when you have exceptional and/or irrational portability requirements.
I was curious with this:
What is the diference between:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
and:
char Buffer[MAX_BUF];
Case 1: In
char Buffer[MAX_BUF];
Buffer is an array of size MAX_BUF. The allocation technique is called VLA.
Case 2: In
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
Buffer is a pointer which is allocated a memory of size MAX_BUF which is 1000.
and, an array is not the same as a pointer, and C-FAQ has a Very Good collection detailing the reasons.
The major difference, in terms of usability and behaviour are:
(1) is on stack, usually Note, while (2) is on heap, always.
(1) has fixed size once allocated, (2) can be resized.
(1) is allocated when the enclosing function is called and has the block scope OTOH, (2) is allocated memory dynamically, at runtime and the returned memory has a lifetime which extends from the allocation until the deallocation.
(1) allocated memory need not be managed by programmer, while in (2) all malloc()d memory should be free()d. [Courtesy: Giorgi]
Note: Wiki
For example, the GNU C Compiler allocates memory for VLAs on the stack.
I will add a bit info in terms of memory management, in addition to what others said.
1) The main difference is here:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
You need to manage the allocated memory manually, e.g., free Buffer when you are done using it. Forgetting to free it (or freeing it twice) may lead to trouble.
2) With the second case:
char Buffer[MAX_BUF];
You don't need to free anything. It will get destroyed automatically. Hence you avoid the task of handling the memory - which is good.
You should try to evaluate always which approach you need.
Some points.
Since second is allocated on stack, the first approach is taken also when large array needs to be created - since more memory is usually available on the heap.
Also if you create array using second approach for example in the method, the life time of the object will be that method - you will not be able to use that array outside that method. Whereas with dynamic allocation that is not the case.
char* Buffer = malloc(MAX_BUF);
creates a char pointer Buffer, dynamically allocates MAX_BUF bytes of memory via the malloc and makes Buffer point to the start of the allocated space. This memory is allocated on the heap.
char Buffer[MAX_BUF];
creates an array Buffer of size MAX_BUF which can hold a maximum of MAX_BUF characters. Note that you are creating a Variable Length Array (a feature introduced in C99) since MAX_BUF is a variable. This array may be created on the stack.
The most notable difference is scope. The VLA array will only be valid inside the scope where it is declared, while a dynamic array will be available everywhere in the program until you call free().
In practice, VLAs may be faster than dynamic memory, in case the compiler use stack allocation for the VLA. It is however not specified by the C standard where a VLA is allocated.
(A compiler could in theory allocate a VLA on the heap, but then the compiler would also be responsible for the clean-up. I don't think any such solutions exist. Every compiler I've used always declare VLAs on the stack.)
This means that VLAs are unsuitable to hold large amounts of data: you would risk stack overflow. This is not a concern when you are using dynamic memory however.
VLAs don't have the same portability as dynamic arrays, since awfully old compilers don't support VLAs. In theory, new C11 compilers don't have to suport VLAs either, though at this point I know of no compiler has been stupid enough to drop that support.
Comparison/summary:
VLAs should be used when there are small amounts of local data, because they have fast allocation time and automatic clean-up.
Dynamic arrays should be used when there are large amounts of data, to prevent stack overflow.
Dynamic arrays should be used when the data needs to persist after the execution of a function and be available elsewhere in the program.
Dynamic arrays should be used when you have exceptional and/or irrational portability requirements.
I was curious with this:
What is the diference between:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
and:
char Buffer[MAX_BUF];
Case 1: In
char Buffer[MAX_BUF];
Buffer is an array of size MAX_BUF. The allocation technique is called VLA.
Case 2: In
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
Buffer is a pointer which is allocated a memory of size MAX_BUF which is 1000.
and, an array is not the same as a pointer, and C-FAQ has a Very Good collection detailing the reasons.
The major difference, in terms of usability and behaviour are:
(1) is on stack, usually Note, while (2) is on heap, always.
(1) has fixed size once allocated, (2) can be resized.
(1) is allocated when the enclosing function is called and has the block scope OTOH, (2) is allocated memory dynamically, at runtime and the returned memory has a lifetime which extends from the allocation until the deallocation.
(1) allocated memory need not be managed by programmer, while in (2) all malloc()d memory should be free()d. [Courtesy: Giorgi]
Note: Wiki
For example, the GNU C Compiler allocates memory for VLAs on the stack.
I will add a bit info in terms of memory management, in addition to what others said.
1) The main difference is here:
const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);
You need to manage the allocated memory manually, e.g., free Buffer when you are done using it. Forgetting to free it (or freeing it twice) may lead to trouble.
2) With the second case:
char Buffer[MAX_BUF];
You don't need to free anything. It will get destroyed automatically. Hence you avoid the task of handling the memory - which is good.
You should try to evaluate always which approach you need.
Some points.
Since second is allocated on stack, the first approach is taken also when large array needs to be created - since more memory is usually available on the heap.
Also if you create array using second approach for example in the method, the life time of the object will be that method - you will not be able to use that array outside that method. Whereas with dynamic allocation that is not the case.
char* Buffer = malloc(MAX_BUF);
creates a char pointer Buffer, dynamically allocates MAX_BUF bytes of memory via the malloc and makes Buffer point to the start of the allocated space. This memory is allocated on the heap.
char Buffer[MAX_BUF];
creates an array Buffer of size MAX_BUF which can hold a maximum of MAX_BUF characters. Note that you are creating a Variable Length Array (a feature introduced in C99) since MAX_BUF is a variable. This array may be created on the stack.
The most notable difference is scope. The VLA array will only be valid inside the scope where it is declared, while a dynamic array will be available everywhere in the program until you call free().
In practice, VLAs may be faster than dynamic memory, in case the compiler use stack allocation for the VLA. It is however not specified by the C standard where a VLA is allocated.
(A compiler could in theory allocate a VLA on the heap, but then the compiler would also be responsible for the clean-up. I don't think any such solutions exist. Every compiler I've used always declare VLAs on the stack.)
This means that VLAs are unsuitable to hold large amounts of data: you would risk stack overflow. This is not a concern when you are using dynamic memory however.
VLAs don't have the same portability as dynamic arrays, since awfully old compilers don't support VLAs. In theory, new C11 compilers don't have to suport VLAs either, though at this point I know of no compiler has been stupid enough to drop that support.
Comparison/summary:
VLAs should be used when there are small amounts of local data, because they have fast allocation time and automatic clean-up.
Dynamic arrays should be used when there are large amounts of data, to prevent stack overflow.
Dynamic arrays should be used when the data needs to persist after the execution of a function and be available elsewhere in the program.
Dynamic arrays should be used when you have exceptional and/or irrational portability requirements.
People seem to say how malloc is so great when using arrays and you can use it in cases when you don't know how many elements an array has at compile time(?). Well, can't you do that without malloc? For example, if we knew we had a string that had max length 10 doesn't the following do close enough to the same thing?... Besides being able to free the memory that is.
char name[sizeof(char)*10];
and
char *name = malloc(sizeof(char)*10);
The first creates an array of chars on the stack. The length of the array will be sizeof(char)*10, but seeing as char is defined by the standard of being 1 in size, you could just write char name[10];
If you want an array, big enough to store 10 ints (defined per standard to be at least 2 bytes in size, but most commonly implemented as 4 bytes big), int my_array[10] works, too. The compiler can work out how much memory will be required anyways, no need to write something like int foo[10*sizeof(int)]. In fact, the latter will be unpredictable: depending on sizeof(int), the array will store at least 20 ints, but is likely to be big enough to store 40.
Anyway, the latter snippet calls a function, malloc wich will attempt to allocate enough memory to store 10 chars on the heap. The memory is not initialized, so it'll contain junk.
Memory on the heap is slightly slower, and requires more attention from you, who is writing the code: you have to free it explicitly.
Again: char is guaranteed to be size 1, so char *name = malloc(10); will do here, too. However, when working with heap memory, I -and I'm not alone in this- prefer to allocate the memory like so some_ptr = malloc(10*sizeof *some_ptr); using *some_ptr, is like saying 10 times the size of whatever type this pointer will point to. If you happen to change the type later on, you don't have to refactor all malloc calls.
General rule of thumb, to answer your question "can you do without malloc", is that you don't use malloc, unless you have to.
Stack memory is faster, and easier to use, but it is less abundant. This site was named after a well-known issue you can run into when you've pushed too much onto the stack: it overflows.
When you run your program, the system will allocate a chunk of memory that you can use freely. This isn't much, but plenty for simple computations and calling functions. Once you run out, you'll have to resort to allocating memory from the heap.
But in this case, an array of 10 chars: use the stack.
Other things to consider:
An array is a contguous block of memory
A pointer doesn't know/can't tell you how big a block of memory was allocated (sizeof(an_array)/sizeof(type) vs sizeof(a_pointer))
An array's declaration does not require the use of sizeof. The compiler works out the size for you: <type> my_var[10] will reserve enough memory to hold 10 elements of the given type.
An array decays into a pointer, most of the time, but that doesn't make them the same thing
pointers are fun, if you know what you're doing, but once you start adding functions, and start passing pointers to pointers to pointers, or a pointer to a pointer to a struct, that has members that are pointers... your code won't be as jolly to maintain. Starting off with an array, I find, makes it easier to come to grips with the code, as it gives you a starting point.
this answer only really applies to the snippets you gave, if you're dealing with an array that grows over time, than realloc is to be preferred. If you're declaring this array in a recursive function, that runs deep, then again, malloc might be the safer option, too
Check this link on differences between array and pointers
Also take a look at this question + answer. It explains why a pointer can't give you the exact size of the block of memory you're working on, and why an array can.
Consider that an argument in favour of arrays wherever possible
char name[sizeof(char)*10]; // better to use: char name[10];
Statically allocates a vector of sizeof(char)*10 char elements, at compile time. The sizeof operator is useless because if you allocate an array of N elements of type T, the size allocated will already be sizeof(T)*N, you don't need to do the math. Stack allocated and no free needed. In general, you use char name[10] when you already know the size of the object you need (the length of the string in this case).
char *name = malloc(sizeof(char)*10);
Allocates 10 bytes of memory in the heap. Allocation is done at run time, you need to free the result.
char name[sizeof(char)*10];
The first one is allocated on the stack, once it goes out of scope memory gets automatically freed. You can't change the size of the first one.
char *name = malloc(sizeof(char)*10);
The second one is allocated on the heap and should be freed with free. It will stick around otherwise for the lifetime of your application. You can reallocate memory for the second one if you need.
The storage duration is different:
An array created with char name[size] exists for the entire duration of program execution (if it is defined at file scope or with static) or for the execution of the block it is defined in (otherwise). These are called static storage duration and automatic storage duration.
An array created with malloc(size) exists for just as long as you specify, from the time you call malloc until the time you call free. Thus, it can be made to use space only while you need it, unlike static storage duration (which may be too long) or automatic storage duration (which may be too short).
The amount of space available is different:
An array created with char name[size] inside a function uses the stack in typical C implementations, and the stack size is usually limited to a few megabytes (more if you make special provisions when building the program, typically less in kernel software and embedded systems).
An array created with malloc may use gigabytes of space in typical modern systems.
Support for dynamic sizes is different:
An array created with char name[size] with static storage duration must have a size specified at compile time. An array created with char name[size] with automatic storage duration may have a variable length if the C implementation supports it (this was mandatory in C 1999 but is optional in C 2011).
An array created with malloc may have a size computed at run-time.
malloc offers more flexibility:
Using char name[size] always creates an array with the given name, either when the program starts (static storage duration) or when execution reaches the block or definition (automatic).
malloc can be used at run-time to create any number of arrays (or other objects), by using arrays of pointers or linked lists or trees or other data structures to create a multitude of pointers to objects created with malloc. Thus, if your program needs a thousand separate objects, you can create an array of a thousand pointers and use a loop to allocate space for each of them. In contrast, it would be cumbersome to write a thousand char name[size] definitions.
First things first: do not write
char name[sizeof(char)*10];
You do not need the sizeof as part of the array declaration. Just write
char name[10];
This declares an array of 10 elements of type char. Just as
int values[10];
declares an array of 10 elements of type int. The compiler knows how much space to allocate based on the type and number of elements.
If you know you'll never need more than N elements, then yes, you can declare an array of that size and be done with it, but:
You run the risk of internal fragmentation; your maximum number of bytes may be N, but the average number of bytes you need may be much smaller than that. For example, let's say you want to store 1000 strings of max length 255, so you declare an array like
char strs[1000][256];
but it turns out that 900 of those strings are only 20 bytes long; you're wasting a couple of hundred kilobytes of space1. If you split the difference and stored 1000 pointers, then allocated only as much space as was necessary to store each string, then you'd wind up wasting a lot less memory:
char *strs[1000];
...
strs[i] = strdup("some string"); // strdup calls malloc under the hood
...
Stack space is also limited relative to heap space; you may not be able to declare arbitrarily large arrays (as auto variables, anway). A request like
long double huge[10000][10000][10000][10000];
will probably cause your code to crash at runtime, because the default stack size isn't large enough to accomodate it2.
And finally, most situations fall into one of three categories: you have 0 elements, you have exactly 1 element, or you have an unlimited number of elements. Allocating large enough arrays to cover "all possible scenarios" just doesn't work. Been there, done that, got the T-shirt in multiple sizes and colors.
1. Yes, we live in the future where we have gigabytes of address space available, so wasting a couple of hundred KB doesn't seem like a big deal. The point is still valid, you're wasting space that you don't have to.
2. You could declare very large arrays at file scope or with the static keyword; this will allocate the array in a different memory segment (neither stack nor heap). The problem is that you only have that single instance of the array; if your function is meant to be re-entrant, this won't work.
From what I understand, the malloc function takes a variable and allocates memory as asked. In this case, it will ask the compiler to prepare memory in order to fit the equivalence of twenty double variables. Is my way of understanding it correctly, and why must it be used?
double *q;
q=(double *)malloc(20*sizeof(double));
for (i=0;i<20; i++)
{
*(q+i)= (double) rand();
}
You don't have to use malloc() when:
The size is known at compile time, as in your example.
You are using C99 or C2011 with VLA (variable length array) support.
Note that malloc() allocates memory at runtime, not at compile time. The compiler is only involved to the extent that it ensures the correct function is called; it is malloc() that does the allocation.
Your example mentions 'equivalence of ten integers'. It is very seldom that 20 double occupy the same space as 10 int. Usually, 10 double will occupy the same space as 20 int (when sizeof(int) == 4 and sizeof(double) == 8, which is a very commonly found setting).
It's used to allocate memory at run-time rather than compile-time. So if your data arrays are based on some sort of input from the user, database, file, etc. then malloc must be used once the desired size is known.
The variable q is a pointer, meaning it stores an address in memory. malloc is asking the system to create a section of memory and return the address of that section of memory, which is stored in q. So q points to the starting location of the memory you requested.
Care must be taken not to alter q unintentionally. For instance, if you did:
q = (double *)malloc(20*sizeof(double));
q = (double *)malloc(10*sizeof(double));
you will lose access to the first section of 20 double's and introduce a memory leak.
When you use malloc you are asking the system "Hey, I want this many bytes of memory" and then he will either say "Sorry, I'm all out" or "Ok! Here is an address to the memory you wanted. Don't lose it".
It's generally a good idea to put big datasets in the heap (where malloc gets your memory from) and a pointer to that memory on the stack (where code execution takes place). This becomes more important on embedded platforms where you have limited memory. You have to decide how you want to divvy up the physical memory between the stack and heap. Too much stack and you can't dynamically allocate much memory. Too little stack and you can function call your way right out of it (also known as a stack overflow :P)
As the others said, malloc is used to allocate memory. It is important to note that malloc will allocate memory from the heap, and thus the memory is persistent until it is free'd. Otherwise, without malloc, declaring something like double vals[20] will allocate memory on the stack. When you exit the function, that memory is popped off of the stack.
So for example, say you are in a function and you don't care about the persistence of values. Then the following would be suitable:
void some_function() {
double vals[20];
for(int i = 0; i < 20; i++) {
vals[i] = (double)rand();
}
}
Now if you have some global structure or something that stores data, that has a lifetime longer than that of just the function, then using malloc to allocate that memory from the heap is required (alternatively, you can declare it as a global variable, and the memory will be preallocated for you).
In you example, you could have declared double q[20]; without the malloc and it would work.
malloc is a standard way to get dynamically allocated memory (malloc is often built above low-level memory acquisition primitives like mmap on Linux).
You want to get dynamically allocated memory resources, notably when the size of the allocated thing (here, your q pointer) depends upon runtime parameters (e.g. depends upon input). The bad alternative would be to allocate all statically, but then the static size of your data is a strong built-in limitation, and you don't like that.
Dynamic resource allocation enables you to run the same program on a cheap tablet (with half a gigabyte of RAM) and an expensive super-computer (with terabytes of RAM). You can allocate different size of data.
Don't forget to test the result of malloc; it can fail by returning NULL. At the very least, code:
int* q = malloc (10*sizeof(int));
if (!q) {
perror("q allocation failed");
exit(EXIT_FAILURE);
};
and always initialize malloc-ed memory (you could prefer using calloc which zeroes the allocated memory).
Don't forget to later free the malloc-ed memory. On Linux, learn about using valgrind. Be scared of memory leaks and dangling pointers. Recognize that the liveness of some data is a non-modular property of the entire program. Read about garbage collection!, and consider perhaps using Boehm's conservative garbage collector (by calling GC_malloc instead of malloc).
You use malloc() to allocate memory dynamically in C. (Allocate the memory at the run time)
You use it because sometimes you don't know how much memory you'll use when you write your program.
You don't have to use it when you know thow many elements the array will hold at compile time.
Another important thing to notice that if you want to return an array from a function, you will want to return an array which was not defined inside the function on the stack. Instead, you'll want to dynamically allocate an array (on the heap) and return a pointer to this block:
int *returnArray(int n)
{
int i;
int *arr = (int *)malloc(sizeof(int) * n);
if (arr == NULL)
{
return NULL;
}
//...
//fill the array or manipulate it
//...
return arr; //return the pointer
}