If I for example define an array
char string[20] = "something";
And function
void f(char* somestring[])
What is this, an address or a number or what and how can I work with this? In which purposes is it used?
If I for example define an array
char string[20] = "something";
And function
void f(char* somestring[])
What is this, an address or a number or what and how can I work with this? In which purposes is it used?
First, an address is a number. Then, type char *foo[]
(which really is just char **foo
) has several equivalent interpretations.
foo
is a doubly indexed char
array.foo
is a pointer to a char
array (that is, a string if it's null terminated like a string literal is).foo
is a pointer, to a pointer to a char
value.It can be used in several ways as well.
foo
is a char 2-dimensional array ; then foo[x][y]
retrieves you the character in the array at row x
and column y
.foo
is a pointer to a string. Then (*foo)[x]
gives you the x
-th character of the string.**foo
to set the char
value, and *foo
to change the character pointed to by the pointer.EDIT: of course, all these are composeable and equivalent. For instance, foo[0][0]
is just (*foo)[0]
which is just **foo
.
string
is a 20-element array of char
- you can store a string of up to 19 characters (need to reserve one element for the string terminator), or you can store a sequence of 20 characters that does not represent a string (like a hash value or something).
Except when it is the operand of the sizeof
or unary &
operators, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
", and its value will be the address of the first element of the array.
So, if you passed string
as an argument to a function, like so:
f( string );
what the function actually receives is a pointer value:
void f( char *somestring ) { ... }
In the context of a function parameter declaration (and only in that context), T a[N]
and T a[]
are both treated as T *a
, so you could declare f
to be any of
void f( char somestring[20] ) { ... }
or
void f( char somestring[] ) { ... }
as well.
The subscript operator []
is defined to work on pointer expressions as well as array expressions, so you can still use []
to index into somestring
like any other array:
void f( char *somestring )
{
int i = 0;
while ( somestring[i++] )
{
// do something interesting with somestring[i]
}
}
So, if void f( char *somestring )
is the same as void f( char somestring[] )
, then what do we make of
void f( char *somestring[] )
?
In this case, it's clear that somestring
is meant to be an array of pointers to char
, something like
char *strings[] = {"foo", "bar", "bletch", ... };
Each strings[i]
stores the address of the corresponding string literal, not the contents of the string itself. By the same rule above, the prototype may also be written as
void f( char **somestring ) { ... }
or
void f( char *somestring[N] ) { ... }
The one thing somestrings
is not in this case is a 2D array of char
. If strings
had been declared
#define N ... // number of strings
#define M ... // maximum length of string
char strings[N][M+1] = {"foo", "bar", "bletch", ... };
then, if we pass strings
to f
, it would "decay" to
void f( char (*somestrings)[M+1] ) { ... }
The the type of strings
is "N-element array of M+1-element array of char
", so the expression "decays" to "pointer to M+1-element array of char
".