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
arrdegrades 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 malloced 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.