Is the same
char* s1[size];
To
char** s2 = malloc(size * sizeof(char*));
They have any difference?
Is the same
char* s1[size];
To
char** s2 = malloc(size * sizeof(char*));
They have any difference?
Theoretically, *arr[]
and **arr
are different. For example :
char *arr[size]; //case 1
Here arr
is a an array of size size
whose elements are of the type char*
Whereas,
char **arr; //case2
Here arr
is itself a pointer to the type char*
Note: In case 1 array
arr
degrades to a pointer to become the typechar**
but it's not possible the other way around i.e, pointer in case 2 cannot become an array.
There are few differences:
s1
is not an lvalue, so it cannot be modified (e.g. using assignment or increment operators). Because of this it resembles type char** const s1
which also does not allow modifications (but in this case this is caused by const
modifier).operator &
used on address of array will return address of array (i.e. address of 1st element). When &
will be used on variable, it will return its address:
assert((void*)&s1 == (void*)s1);
assert((void*)&s2 != (void*)s2);
sizeof()
used on array will return array size, while sizeof()
used on pointer will return pointer size - usually it will be the same as sizeof(void*)
, but C standard does not require this (see comments below):
assert(sizeof(s1) == size * sizeof(char*));
assert(sizeof(s1) == size * sizeof(s1[0])); // this is the same
assert(sizeof(s2) == sizeof(void*)); // on some platforms this may fail
and of course obvious one - s1
is allocated on stack, s2
on heap. Because of this s1
will be destroyed automatically when execution leaves current scope, and s2
requires call to free
to release memory.
Update: here is example code which checks above asserts:
#include <assert.h>
#include <stdlib.h>
int main()
{
const int size = 22;
char* s1[size];
char** s2 = (char**)malloc(size * sizeof(char*));
assert((void*)&s1 == (void*)s1);
assert((void*)&s2 != (void*)s2);
assert(sizeof(s1) == size * sizeof(char*));
assert(sizeof(s1) == size * sizeof(s1[0])); // this is the same
assert(sizeof(s2) == sizeof(void*)); // on some platforms this may fail
free(s2);
// Attempts to modify value
char** const s3 = s1;
++s2;
//++s1; // compilation error - lvalue required as increment operand
//++s3; // compilation error - increment of read-only variable ‘s3’
return 0;
}
char* s1[size];
Is an array of pointers of type char
that is allocated on the stack.
char** s2 = malloc(size * sizeof(char*));
Is a pointer of type char **
that is allocated on the stack but points to a dynamic array of pointers of type char *
allocated on the heap.
The two differ in terms of scope and the usual difference between arrays and pointers.
s1
is an array, s2
is a pointer. s2
points to the first element of the malloc
ed array.
The array s1
has automatic storage duration, while the array which s2
points to has dynamic storage duration.
Also, in C89 char* s1[size];
is valid only if size
is a constant expression, because C89 doesn't support variable-length arrays.