Если я, например, определяю массив
char string[20] = "something";
И функция
void f(char* somestring[])
Что это, адрес или номер или что и как с этим работать? В каких целях используется?
См. В чем разница между массивом char и указателем char в c? и Является ли имя массива указателем?.
Последняя часть вопроса слишком широка, чтобы ответить здесь.





Во-первых, адрес — это число. Затем тип char *foo[] (который на самом деле просто char **foo) имеет несколько интерпретаций эквивалент.
foo — массив с двойным индексом char.foo — это указатель на массив char (то есть строку, если она завершается нулем, как строковый литерал).foo — это указатель на указатель на значение char.Его также можно использовать несколькими способами.
foo — двумерный массив символов; затем foo[x][y] возвращает вам символ в массиве в строке x и столбце y.foo — указатель на строку. Затем (*foo)[x] дает вам x-й символ строки.**foo, чтобы установить значение char, и *foo, чтобы изменить символ, на который указывает указатель.РЕДАКТИРОВАТЬ: конечно, все они составные и эквивалентны. Например, foo[0][0] — это просто (*foo)[0], а это просто **foo.
string — это массив из 20 элементов char — вы можете хранить нить до 19 символов (необходимо зарезервировать один элемент для ограничителя строки) или вы можете хранить последовательность из 20 символов, которая представляет нет строку (например, хеш-значение или что-то в этом роде).
За исключением случаев, когда это операнд оператора sizeof или унарного &, выражение типа «N-элементный массив T» будет преобразован («распад») в выражение типа «указатель на T», и его значение будет адрес первого элемента массива.
Итак, если вы передали string в качестве аргумента функции, вот так:
f( string );
то, что функция фактически получает, является значением указателя:
void f( char *somestring ) { ... }
В контексте объявления параметра функции (и Только в этом контексте) T a[N] и T a[] обрабатываются как T *a, поэтому вы можете объявить f любым из
void f( char somestring[20] ) { ... }
или
void f( char somestring[] ) { ... }
также.
Оператор индекса [] предназначен для работы с выражениями указателя, а также с выражениями массива, поэтому вы все равно можете использовать [] для индексации в somestring, как и любой другой массив:
void f( char *somestring )
{
int i = 0;
while ( somestring[i++] )
{
// do something interesting with somestring[i]
}
}
Итак, если void f( char *somestring ) такое же, как void f( char somestring[] ), то что мы делаем из
void f( char *somestring[] )
?
В этом случае ясно, что somestring должен быть массивом указатели наchar, что-то вроде
char *strings[] = {"foo", "bar", "bletch", ... };
Каждый strings[i] хранит адрес соответствующего строкового литерала, а не содержимое самой строки. По тому же правилу, что и выше, прототип может быть записан как
void f( char **somestring ) { ... }
или
void f( char *somestring[N] ) { ... }
Одна вещь somestrings — это нет, в данном случае это двумерный массив char. Если бы strings было объявлено
#define N ... // number of strings
#define M ... // maximum length of string
char strings[N][M+1] = {"foo", "bar", "bletch", ... };
то, если мы перейдем от strings к f, оно «распадется» до
void f( char (*somestrings)[M+1] ) { ... }
Тип strings - это «массив N-элементов из M+1-элементного массива char», поэтому выражение «распадается» до «указатель на M+1-элементный массив char».
string— это множество из 20charс.somestring— это указатель для указателя наchar.