The following code creates an array with the malloc function. But i know that this can be done much simplier with just int array[size]. I think this is static array. But with the malloc function is it dynamic array? I found this code in the net... What is really happening and whats the difference between a static array and a dynamic array(and static memory between heap memory). Can you change the size of the dynamic array during runtime? or... what i dont know exactly... If someone could explain i would appreciate :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int size;
int i;
printf("Choose size of array: ");
scanf("%d",&size);
/*---MALLOC/FREE---*/
int *m_array = (int *)malloc((size+1)*sizeof(int));
memset(m_array,'\0',size+1);
for(i=0; i<size ; i++)
{
m_array[i]=i;
printf("%d ",m_array[i]);
}
printf("\n");
free(m_array);
return 0;
}
You're using dynamic arrays of size+1 and adding elements to it (from 0 to size) and releasing the space at the end before returning 0. So when in your case, int *m_array is a pointer to an int. What you're doing on line 13 is declaration:
and allocation:
Since it is a dynamic array, you are allocating on heap and is kept until it is freed (that's why you have free(m_array) at the end). If it was static, you could've initialized the array this way:
And it would've been allocated on static storage area (unless is automatic) and would be deallocated as soon as the program ended. You can't change the size of an static array in C, so you need to use a dynamic array. You use realloc when you want to change to size of a dynamic array.
Static arrays are allocated memory at compile time and the memory is allocated on the stack. Whereas, the dynamic arrays are allocated memory at the runtime and the memory is allocated from heap.
This is static integer array i.e. fixed memory assigned before runtime
This is dynamic integer array i.e memory assigned on runtime
There are several flavors of arrays, depending on how and where they are declared.
Fixed-length Arrays
Fixed-length arrays must have their size determined at compile time. You cannot change the size of a fixed-length array after it has been defined.
Fixed-length arrays are declared in one of the following ways:
In the first three cases,
N
must be a constant expression whose value must be known at compile time. In the first three cases, the size of the array is taken fromN
; in the last two cases, it's taken from the number of elements in the initializer list or the size of the string literal.The initial contents of a fixed-length array depend on its storage duration and whether an initializer has been supplied.
If the array has
static
storage duration (meaning it was declared at file scope outside of any function body, or was declared with thestatic
keyword) and no initializer is present, then all of the array elements are initialized to0
(for scalars) orNULL
(for pointers). IfT
is an aggregate type such as astruct
or an array type, then each member of the aggregate is initialized with a0
orNULL
.union
types are similarly zeroed out.If the array has
auto
storage duration (meaning it was declared within a function or block without thestatic
keyword) and no initializer is present, then the contents of the array are indeterminate - basically, garbage.If the array is declared with an initializer list (regardless of storage duration), then the initial values of the array elements correspond to the initializer. If there are fewer elements in the initializer than the array (for example,
N
is 10 but you only initialize the first 5 elements), then the remaining elements are initialized as though the array hadstatic
storage duration. IOW, given the declarationthen the initial contents of the array are
{0, 1, 2, 0, 0, 0, 0, 0, 0, 0}
.Fixed-length arrays containing string values may be initialized using a string literal. C allows for "wide" character strings, so
char_type
may be eitherchar
orwchar_t
. The rules are the same for regular initializer lists, except thatN
(if specified) must be at least 1 more than the length of the string to account for the string terminator.This means that
will be initialized as
{'t', 'e', 's', 't', 0, 0, 0, 0, 0, 0}
andwill be initialized as
{'t', 'e', 's', 't', 0}
.Arrays with
static
storage duration are stored such that they are available as soon as the program is loaded, and aren't released until the program exits. This usually means that they're stored in a memory segment like.data
or.bss
(or the equivalent for whatever executable format your system uses).Arrays with
auto
storage duration are stored such that they are allocated at block or function entry and released at block or function exit (in practice, they'll probably be allocated at function entry, regardless of whether they're limited to a smaller scope within the function) - this typically translates to the stack, although it doesn't have to.Variable-length Arrays
Variable-length arrays were added in C99 - they behave mostly like fixed-length arrays, except that their size is established at run time;
N
does not have to be a compile-time constant expression:Contrary to what their name implies, you cannot change the size of a variable-length array after it has been defined. "Variable-length" simply means that the size isn't fixed at compile time, and can change from definition to definition.
Since their size isn't set until runtime, variable-length arrays may not be declared at file scope or with the
static
keyword, nor can they be declared with an initializer list. Exactly how the space for VLAs is managed is up to the implementation; it may be (and usually is) taken from the stack, but AFAIK may be taken from somewhere else.Dynamic Arrays
Dynamic arrays are not really "arrays" as such, at least in terms of the data types of the objects we use to manage them. Dynamic arrays are allocated at runtime using one of
malloc
,calloc
, orrealloc
, and that storage is held until released with a call tofree
.A dynamic array may be resized using the
realloc
library function, like so:While the memory for the array elements themselves is taken from the heap (or whatever dynamic memory pool), the memory for the pointer variable
p
will be allocated from either a.bss
or.data
segment or from the stack, based onp
's storage duration (static
orauto
).Memory allocated with
malloc
orrealloc
is not initialized; the contents of that memory will be indeterminate. Memory allocated withcalloc
will be initialized with zeros.Arrays vs. Pointers
At some point, somebody is going to tell you that "an array is just a pointer". That person is not correct.
When you declare an array (either fixed- or variable-length), enough storage is set aside for the elements of that array and nothing else; no storage is set aside for any metadata such as the array length or a pointer to the first element. Given the declaration
then the storage will look something like this:
There is no object
a
apart from the array elements themselves (or, more properly, the objecta
is the elements of the array), and the expressiona
may not be the target of an assignment.But...
The expression
a[i]
is defined as*(a + i)
; that is, given a pointer valuea
, offseti
elements (not bytes!) from that address and dereference the result. But ifa
is not a pointer, how can that work?Like this - except when it is the operand of the
sizeof
or unary&
operators, or is a string literal used as an array initializer in a declaration, an expression of type "N
-element array ofT
" will be converted ("decay") to an expression of type "pointer toT
", and the value of the expression will be the address of the first element of the array.This has several implications:
a
,&a
, and&a[0]
will all yield the same value (the address of the first element of the array), but the types of the expressions will be different (T *
,T (*)[N]
, andT *
, respectively);[]
works equally well with both array expressions and pointer expressions (indeed, it's defined to work on pointer expressions);For dynamic arrays, the situation is different. Given the line
then your storage will look something like this:
In this case,
p
is a separate object from the array. Thus,&p
won't give you the same value asp
and&p[0]
, and its type will beT **
as opposed toT (*)[N]
. Also, sincep
is just a pointer variable, you can assign a new value to it (although if you do so withoutfree
ing the memory it points to first, you'll create a memory leak).Similarly,
sizeof p
won't behave likesizeof a
; it will simply return the size of the pointer variable, not the size of the allocated memory that the pointer points to.