char ** argv
is a null terminated array in C according to the C standard. (EDIT: see clarification below) C doesn't care about types at all and you can abuse this by casting pointers to different (sometimes incompatible types). The second argument to main (argv) it set up by the initialization code and has the same space as a pointer regardless if it's a string, array of strings, struct, integer etc...The existing structure will simply be interpreted as that new type like so:
String1 String2 String3 String4
char ** a2: |0x41414141 |0x42424242 |0x43434343 |0x00000000 |
+-----------+-----------+-----------+-----------+
char * a1 : |41|41|41|41|42|42|42|42|43|43|43|43|00|00|00|00|
printf("%s\n", a1);
> AAAABBBBCCCC
That being said, some compilers (clang) will emit an error on the improper type, like so: test.c:3:5: error: second parameter of 'main' (argument array) must be of type
'char **'
int main(int argc, char * argv)
^
1 error generated.char * * is a pointer to a pointer to a char and nothing else, it might be a NULL terminated array or not at all.
C cares about types. Casting a pointer to an incompatible type or reinterpreting through an incompatible pointer is not defined in C( undefined behavior ).
Pointers of different types are allowed to have different sizes. sizeof( char* ) == sizeof( char* * ) is not guaranteed in C.
Also any program whose main is not int main( void ) or int main( int , char* * ) will result in undefined behavior.
All of this is in the latest standard.
Both, segfaulting or running completely normally can be a result of undefined behavior. That is why we really like to avoid it in C. Thus your advice is really not good for a modern C.
> sizeof( char* ) == sizeof( char* * )
True, I forgot that different architectures/compilers can produce different pointer sizes. Thanks!