Массивы символов в C - PullRequest
       18

Массивы символов в C

2 голосов
/ 12 августа 2011

Я новичок в с. Просто задайте вопрос о символьных массивах (или строках) в c: когда я хочу создать массив символов в C, должен ли я одновременно указывать размер?

Потому что мы можем не знать размер, который нам действительно нужен. Например, клиент-серверная программа, если мы хотим объявить массив символов для серверной программы для получения сообщения от клиентской программы, но мы не знаем размер сообщения, мы могли бы сделать это следующим образом:

char buffer[1000];
recv(fd,buffer, 1000, 0);

Но что, если реальное сообщение имеет только длину 10. Это приведет к большой потере памяти?

Ответы [ 6 ]

2 голосов
/ 12 августа 2011

Да, вы должны определить размер заранее, даже если вы используете malloc.

Когда вы читаете из сокетов, как в примере, вы обычно используете буфер с разумным размером и отправляете данные в другую структуру, как только вы их используете. В любом случае, 1000 байтов - это не такая большая трата памяти, и это, безусловно, быстрее, чем запрашивать байт за раз у какого-то менеджера памяти:)

1 голос
/ 12 августа 2011

Да, вы должны указать размер, если вы не инициализируете массив символов во время объявления. Лучший подход к вашей проблеме - определить оптимальный размер буфера во время выполнения и динамически распределить память.

0 голосов
/ 27 мая 2015

Даже если вы используете malloc, вы также должны сначала определить размер! Таким образом, вместо этого вы даете большое число, которое способно принять сообщение как:

int buffer[2000];   

В случае небольшого или большого сообщения вы можете перераспределить его, чтобы освободить неиспользуемые местоположения или занять неиспользуемые местоположения

example:
int main()
{
 char *str;

  /* Initial memory allocation */
  str = (char *) malloc(15);
  strcpy(str, "tutorialspoint");
  printf("String = %s,  Address = %u\n", str, str);

  /* Reallocating memory */
  str = (char *) realloc(str, 25);
  strcat(str, ".com");
  printf("String = %s,  Address = %u\n", str, str);

  free(str);

  return(0);
 }

Примечание: обязательно включите библиотеку stdlib.h

0 голосов
/ 12 августа 2011

Если вы не знаете размер a-priori, у вас нет другого выбора, кроме как создать его динамически, используя malloc (или любой другой эквивалентный механизм на выбранном вами языке).

size_t buffer_size = ...; /* read from a DEFINE or from a config file */
char * buffer = malloc( sizeof( char ) * (buffer_size + 1) );

Создание буфера размером m, но получение только входной строки размером n с n < m - не пустая трата памяти, а технический компромисс.

Если вы создаете буфер с размером, близким к предполагаемому вводу, вы рискуете переполнить буфер много, много раз для тех случаев, когда m >> n. Как правило, итерации в буфере связаны с операциями ввода-вывода, поэтому теперь вы можете экономить некоторые байты (что на самом деле не имеет значения в современном оборудовании) за счет потенциального увеличения проблем на другом конце. Специально для клиент-серверных приложений. Если бы мы говорили о встроенных системах с ограниченными ресурсами, это было бы другое дело.

Вы должны беспокоиться о том, чтобы ваши алгоритмы были правильными и надежными. Тогда вы беспокоитесь, если можете, о том, чтобы сбрасывать несколько байтов здесь и там.

Для меня я бы предпочел создать буфер, который в 2-10 раз больше, чем средний вход (не самый маленький вход, как в вашем случае, а средний), предполагая, что мой вход имеет медленное стандартное отклонение размер. В противном случае я бы пошел в 20 раз больше или больше (особенно если память дешевая, и это минимизирует попадание на диск или карту NIC.)

При самой базовой установке размер буфера обычно получается в виде элемента конфигурации, считываемого из файла (или передаваемого в качестве аргумента), и по умолчанию равным default compile time value, если ничего не указано. Затем вы можете настроить размер ваших буферов в соответствии с наблюдаемыми размерами ввода.

Более сложные алгоритмы (скажем, TCP) корректируют размер своих буферов во время выполнения, чтобы лучше приспосабливать ввод, размер которого может / будет меняться со временем.

0 голосов
/ 12 августа 2011

Если вы не знаете точный объем входных данных, сделайте следующее:

  1. Создать небольшой буфер
  2. Выделите немного памяти для «хранения» (например, в два раза больше размера буфера)
  3. Заполнить буфер данными из входного потока (например, сокет, файл и т. Д.)
  4. Скопировать данные из буфера в хранилище

    4.1 Если в хранилище недостаточно места, перераспределить память (например, с размером, в два раза превышающим его на данный момент)

  5. Выполните шаги 3 и 4, если только «КОНЕЦ ПОТОКА»

    Ваше хранилище содержит данные сейчас.

0 голосов
/ 12 августа 2011

То, о чем вы спрашиваете, это как динамически изменять размер буфера.Это делается с помощью динамического выделения, такого как malloc() - распределитель памяти.Использование этого дает вам важную ответственность: когда вы закончите использовать буфер, вы должны вернуть его в систему самостоятельно.Если вы используете malloc () [или calloc ()], вы возвращаете его с free().

Например:

char *buffer; // pointer to a buffer -- essentially an unsized array
buffer = (char *)malloc(size);
// use the buffer ...
free(buffer); // return the buffer -- do NOT use it any more!

Единственная проблема, которую нужно решить, это как определить размертебе понадобиться.Если вы используете recv () для данных, которые намекают на размер, вам нужно разбить соединение на два вызова recv (): сначала получите минимальный размер, который будут иметь все пакеты, затем выделите полный буфер, затем recv 'Остальное.

...