Нужна динамически размещаемая (инициализированная) статическая переменная - PullRequest
1 голос
/ 25 февраля 2011

Мне нужна статическая строковая (эквивалентная) переменная в C, и у меня возникают проблемы с реализацией чего-то подобного.

Мне нужно добавлять содержимое в эту строку каждый раз, когда вызывается функция.Я пытался с

static char *result = (char*)calloc(0, sizeof(char));

Но таким образом я получил:

ошибка: элемент инициализатора не является постоянным

Что имеет смысл, но я действительноне знаю, как сделать это по-другому (пробовал также с глобальной переменной, но безуспешно).

Кто-нибудь может помочь?

Ответы [ 4 ]

4 голосов
/ 25 февраля 2011

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

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

1 голос
/ 25 февраля 2011

Если вам нужно увеличить длину массива, используйте вместо этого realloc.


char *buf = NULL;

while(/* some loop here */){
    buf = realloc(buf, sizeof(/* new content */));
    ... // copy your new content to buf here
}

Если вы только добавляете контент, может лучше вместо этого использовать списки?

0 голосов
/ 15 мая 2013

Мне удалось заставить это работать для "фиксированного" размера массива, т.е. длина может быть определена во время выполнения, а НЕ во время компиляции.Я создал функцию, которая имеет пустой указатель A в качестве ввода, затем изменяет его внутри и также возвращает его.Длина len - это произвольная длина времени выполнения:

char *malloc_char_array(char* &A, int len);

Затем вызовите эту функцию при инициализации массива:

static char *result = malloc_char_array(result, 50); //test length of 50

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

И функция выделения будет выглядеть как-тонапример:

char *malloc_char_array(char* &A, int len)
{
    A = (char*) malloc(len * sizeof(char));
    return A;
}

При использовании этого метода нет необходимости освобождать «статическую» выделенную память, просто оставьте ее в стеке до завершения работы программы.

0 голосов
/ 25 февраля 2011

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

#define MYDATA_GROW_AMOUNT (12345) //exploit memory alignment on your system
...
/* if the compiler supports it, consider using __thread__ here */
static /* __thread__ */ char  *mydata     = NULL;
static /* __thread__ */ char  *mydata_end = NULL;
static /* __thread__ */ size_t mydata_len = 0;
...
/* gcc? you might want to use
       if(__builtin_expect((mydata_len < required_data_len),0))
   here instead */
if(mydata_len < required_data_len)
{
    mydata_end = mydata + mydata_len;
    mydata_len += MYDATA_GROW_AMOUNT;
    mydata = realloc(mydata,mydata_len);
}
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...