C программирование массива символов или строки в качестве параметра функции - PullRequest
0 голосов
/ 18 марта 2019

Если я, например, определю массив

char string[20] = "something";

И функцию

void f(char* somestring[])

Что это, адрес или число или что и как я могу с этим работать?В каких целях это используется?

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

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 - это , а не , в данном случае2D массив 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».

0 голосов
/ 19 марта 2019

Сначала адрес - это число. Затем тип char *foo[] (который на самом деле просто char **foo) имеет несколько эквивалентных интерпретаций.

  1. foo - дважды индексированный char массив.
  2. foo - указатель на массив char (то есть строка, если она заканчивается нулем, как строковый литерал).
  3. и, возможно, самый редкий вариант использования, foo - указатель на указатель на значение char.

Также может использоваться несколькими способами.

  1. foo - двумерный массив char; затем foo[x][y] возвращает символ в массиве в строке x и столбце y.
  2. foo - указатель на строку. Затем (*foo)[x] дает вам x -й символ строки.
  3. Используйте **foo для установки значения char и *foo для изменения символа, на который указывает указатель.

РЕДАКТИРОВАТЬ : конечно, все они составимы и эквивалентны. Например, foo[0][0] это просто (*foo)[0], что просто **foo.

...