наблюдаемая редукса - отправка нескольких редуксовых действий в одной эпопее

Обработка C массивами очень отличается от Java, и вам придется соответствующим образом скорректировать свое мышление. Массивы в C не являются первоклассными объектами (т. Е. Выражение массива не сохраняет его «массивность» в большинстве контекстов). В C выражение типа «N-элементный массив из T» будет неявно преобразовано («распад») в выражение типа «указатель на T», за исключением случаев, когда выражение массива является операндом sizeof или унарных & операторов, или если выражение массива является строковым литералом, используемым для инициализации другого массива в объявлении.

Между прочим, это означает, что вы не можете передать выражение массива функции и получить его как тип массива ; функция фактически получает тип указателя:

void foo(char *a, size_t asize)
{
  // do something with a
}

int bar(void)
{
  char str[6] = "Hello";
  foo(str, sizeof str);
}

В вызове foo выражение str преобразуется из типа char [6] в char *, поэтому первый параметр foo объявлен char *a вместо char a[6]. В sizeof str, поскольку выражение массива является операндом оператора sizeof, оно не преобразуется в тип указателя, поэтому вы получаете количество байтов в массиве (6).

Если вы заинтересованы в действительно , вы можете прочитать Dennis Ritchie's «Развитие языка C» , чтобы понять, откуда взялось это лечение.

Результатом является то, что функции не могут возвращать типы массивов, что отлично, поскольку выражения массива также не могут быть объектом назначения.

Самый безопасный метод заключается в том, что вызывающий может определить массив и передать его адрес и размер функции, которая должна ее записать:

void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
  ...
  dstArray[i] = some_value_derived_from(srcArray[i]);
  ...
}

int main(void)
{
  char src[] = "This is a test";
  char dst[sizeof src];
  ...
  returnArray(src, sizeof src, dst, sizeof dst);
  ...
}

Другой метод функция для распределения массива динамически и возврата указателя и размера:

char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
  char *dstArray = malloc(srcSize);
  if (dstArray)
  {
    *dstSize = srcSize;
    ...
  }
  return dstArray;
}

int main(void)
{
  char src[] = "This is a test";
  char *dst;
  size_t dstSize;

  dst = returnArray(src, sizeof src, &dstSize);
  ...
  free(dst);
  ...
}

В этом случае вызывающий отвечает за освобождение массива с помощью функции библиотеки free.

Обратите внимание, что dst в приведенном выше коде является простым указателем на char, а не указателем на массив из char. C-указатель и семантика массива таковы, что вы можете применить индексный оператор [] к выражению типа указателя типа или ; оба src[i] и dst[i] будут обращаться к i -му элементу массива (хотя только src имеет тип массива).

Вы можете объявить указатель на N-элементный массив из T и сделать что-то подобное:

char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
  char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
  if (dstArr)
  {
    ...
    (*dstArr)[i] = ...;
    ...
  }
  return dstArr;
}

int main(void)
{
  char src[] = "This is a test";
  char (*dst)[SOME_SIZE];
  ...
  dst = returnArray(src, sizeof src);
  ...
  printf("%c", (*dst)[j]);
  ...
}

Несколько недостатков с приведенным выше. Прежде всего, более старые версии C ожидают, что SOME_SIZE будет константой времени компиляции, что означает, что функция будет работать только с одним размером массива. Во-вторых, вы должны разыменовать указатель перед применением индекса, который загромождает код. Указатели на массивы работают лучше, когда вы имеете дело с многомерными массивами.

30
задан dotintegral 30 November 2016 в 12:44
поделиться