инициализация выделения размера массива - PullRequest
2 голосов
/ 19 августа 2010

gcc 4.4.3 c89

Мне интересно, почему я не могу выделить размер массива при инициализации массива указателей на char.

Я получаю следующую ошибку:

variable-sized object may not be initialized

Это работает нормально.Однако sizeof вернет 4 байта, так как символ * имеет размер 4 байта.Что не очень хорошо, так как это не фактический размер, который я хочу.

void inc_array(const char * const src, size_t size)
{
    /* Array of pointers */
    char *dest[sizeof(src)] = {0};
}

Однако я хочу передать фактический размер и использовать его для инициализации длины массива.

void inc_array(const char * const src, size_t size)
{
    /* Array of pointers */
    char *dest[size] = {0};
}

Какая разница, когда sizeof возвращает size_t, а я передаю size_t?

Большое спасибо за любые предложения,

Ответы [ 4 ]

4 голосов
/ 19 августа 2010

В C89 вы просто не можете этого сделать - массивы переменного размера не поддерживаются до C99.Размеры массива должны быть константами времени компиляции.Вы хотите что-то вроде:

void inc_array(const char * const src, size_t size) {
    char ** dest = calloc(size, sizeof(char*));
    /* do stuff with dest here! */
}

Я не уверен, что вам нужен массив указателей, хотя.Я бы ожидал следующее:

void inc_array(const char * const src, size_t size) {
    char *dest = calloc(size, sizeof(char));
    memcpy(&dest[0], &src[0], size);
    /* do stuff with dest */
    free(dest);
}

Редактировать: Я забыл ответить на вторую часть вашего вопроса .

Разница в том,что sizeof(src) является выражением времени компиляции (IIRC), так как оно вычисляет размер типа.В этом случае он идентичен sizeof(char*), который, вероятно, является 32-разрядным на вашей платформе.Однако size в char *dest[size] невозможно определить статически.Оба значения size_t, но C89 требует, чтобы количество элементов в статически распределенном массиве определялось во время компиляции.Вот почему вы должны прибегнуть к динамическому распределению.

4 голосов
/ 19 августа 2010

Используйте malloc для выделения массивов динамического размера.

Вы также должны убедиться, что malloc ed данные в конечном итоге free d.

2 голосов
/ 19 августа 2010

Как говорится в сообщении об ошибке, массивы переменной длины не могут быть инициализированы, то есть проблема заключается в части = { 0 }Вы все еще можете использовать массив переменной длины - вам просто нужно явно инициализировать его:

void inc_array(const char * const src, size_t size)
{
    /* Array of pointers */
    size_t i;
    char *dest[size];

    for (i = 0; i < size; i++)
        dest[i] = 0;
}
1 голос
/ 19 августа 2010

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

int array[5];
printf("%d\n", sizeof(array) / sizeof(int)); /* prints 5 */

/* ... */

void some_function(int array[])
{
  printf("%d\n", sizeof(array) / sizeof(int)); /* prints 1, no matter what */
}

Как и для определения ваших массивов, в старыхверсии C, массивы переменной длины не допускались (обратите внимание, что Visual Studio все еще реализует эту старую версию C).Вы должны были указать постоянный размер:

const size_t some_size = 22;
size_t some_other_size = 5;
int array1[5]; /* okay */
int array2[some_size]; /* okay */
int array3[some_other_size]; /* not okay - not const */

Более новые версии C (компиляторы, которые реализуют стандарт C99) позволяют указывать переменный размер:

size_t some_other_size = 5;
int array3[some_other_size]; /* okay - VLA */

В качестве примечанияНи одна версия стандарта C ++ не включала поддержку VLA.Однако некоторые компиляторы C ++ реализовали свои собственные расширения (см. Комментарий Groxx).

Если вы хотите выделить переменное количество непрерывной памяти в компиляторе C, который не поддерживает VLA, вы должны использовать malloc ибесплатно, как предположил Кбримингтон:

size_t size = 5;
int* array = (int*)malloc(sizeof(int) * size);
/* use array */
free(array);
...