You can better understand stack vs heap by reading this thread (and the link from that thread as well). I really advise you to read those linked articles.
that confuses me, becasue cant i just do this instead?
So yes, (int*)malloc(3*sizeof(int)); and int x[3]; are both capable of storing 3 integers.
The difference is that the first is allocated on the heap while the latter is allocated on the stack.
So we're back to round 1: what are the stack and the heap? And when should you use one or the other?
In short, the stack should be used when speed matters, but when you want to store a lot of data you can only use the heap (as the stack has limited space). Another reason to use the heap is when your function wants to generate some data and return it to the caller. Since the stack is deallocated when your function returns, you shouldn't return any pointers to any (non-static) stack variable as that memory will be released when the function terminates. You should use the heap (with dynamic memory allocation) instead.
For instance, let's consider the following example where we have two ways to generate a sequence of random digits: GenerateRandomDigitsOnStack and GenerateRandomDigitsOnHeap.
We call both functions in the main() and print the results. You can see that the results show that in the case of GenerateRandomDigitsOnStack, the returned pointer to the array is invalid. By the grace of the compiler, in debug build, it is set to NULL to detect it easier, but if this were a proper release build, no such help would be available, instead it would be some memory garbage and we wouldn't know that we're reading some stale data.
In case of GenerateRandomDigitsOnHeap, we can safely return our allocated pointer, however, we should remember to free it (free(digits);) when we do not need it anymore to prevent memory leaks that would bloat the memory footprint of the application.
Please, also notice that the compiler warns about returning a pointer to a local stack variable.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void GenerateRandomDigits(uint8_t * array, size_t count)
{
for (size_t i = 0; i < count; i++)
{
array[i] = rand() % 10;
printf("%d", array[i]);
}
printf("\n");
}
uint8_t * GenerateRandomDigitsOnStack(size_t count)
{
printf("GenerateRandomDigitsOnStack(count: %lu) returns: ", count);
uint8_t digits[count];
GenerateRandomDigits(digits, count);
return digits;
}
uint8_t * GenerateRandomDigitsOnHeap(size_t count)
{
printf("GenerateRandomDigitsOnHeap(count: %lu) returns: ", count);
uint8_t * digits = (uint8_t *)malloc(sizeof(uint8_t) * count);
GenerateRandomDigits(digits, count);
return digits;
}
void PrintDigits(uint8_t * array, size_t size)
{
printf("PrintDigits(%p, %lu) receives: ", array, size);
if (array == NULL)
{
printf("[invalid array pointer]\n");
return;
}
for (size_t i = 0; i < size; i++)
printf("%d", array[i]);
printf("\n");
}
int main()
{
srand(time(NULL));
size_t count = 10;
uint8_t * digits = GenerateRandomDigitsOnStack(count);
PrintDigits(digits, count);
digits = GenerateRandomDigitsOnHeap(count);
PrintDigits(digits, count);
free(digits); // Only to be used with GenerateRandomDigitsOnHeap(count);
return 0;
}
After running the code, something like this would be the output:
main.c: In function ‘GenerateRandomDigitsOnStack’:
main.c:21:12: warning: function returns address of local variable [-Wreturn-local-addr]
21 | return digits;
| ^~~~~~
GenerateRandomDigitsOnStack(count: 10) returns: 4098928275
PrintDigits((nil), 10) receives: [invalid array pointer]
GenerateRandomDigitsOnHeap(count: 10) returns: 8617229409
PrintDigits(0x55a833cf26b0, 10) receives: 8617229409
I hope this helps answer your questions.
Good luck!