ISO C90 запрещает использование массивов переменной длины [-Werror = vla]

Итак, я создал структуру под названием product, и я хотел отсортировать массив с этим типом структуры на основе компонента этой структуры под названием price, и для этого я скопировал объединенный алгоритм сортировки.

Я немного изменил его, чтобы отсортировать массив так, как я хотел, и он работает, если я скомпилирую файл с помощью обычного gcc. Проблема в том, что я могу скомпилировать файл только с помощью этой команды «gcc -Wall -Wextra -Werror -ansi -pedantic».

Структура:

typedef struct product 
{
   int ident;
   char desc[64]; /* string that describes a product eg. "bread" */
   int price;  /* price of the product*/
   int weight; /* weight of the product eg. 2kg */
   int quant; /* quantity of the product in stock */
   int state_prod;
}product;

Алгоритм объединенной сортировки:

void merge(product arr[], int l, int m, int r)
{ 
    int i, j, k; 
    int n1 = m - l + 1; 
    int n2 =  r - m; 

    product L[n1];  // line of the error
    product R[n2];  // line of the error

    for (i = 0; i < n1; i++) 
        L[i] = arr[l + i]; 
    for (j = 0; j < n2; j++) 
        R[j] = arr[m + 1+ j]; 

    i = 0; 
    j = 0;
    k = l; 
    while (i < n1 && j < n2) 
    { 
        if (L[i].price < R[j].price) 
        { 
            arr[k] = L[i]; 
            i++; 
        } 
        else if (L[i].price == R[j].price)
        {
           if (L[i].ident < R[j].ident)
           {
              arr[k] = L[i]; 
            i++;
           }
           else
           {
              arr[k] = R[j]; 
            j++;
           }
        }
        else
        { 
            arr[k] = R[j]; 
            j++; 
        } 
        k++; 
    } 

    while (i < n1) 
    { 
        arr[k] = L[i]; 
        i++; 
        k++; 
    } 

    while (j < n2) 
    { 
        arr[k] = R[j]; 
        j++; 
        k++; 
    } 
} 

void mergeSort(product arr[], int l, int r)
{ 
    if (l < r) 
    { 
        int m = l+(r-l)/2; 

        mergeSort(arr, l, m); 
        mergeSort(arr, m+1, r); 

        merge(arr, l, m, r); 
    } 
}

При компиляции я получаю эту ошибку:

In function ‘merge’:
error: ISO C90 forbids variable length array ‘L’ [-Werror=vla]
     product L[n1];
     ^~~~~~~
error: ISO C90 forbids variable length array ‘R’ [-Werror=vla]
     product R[n2];
     ^~~~~~~

Серьезно, любая помощь будет оценена по достоинству.


person Martimc.    schedule 30.03.2020    source источник
comment
Сообщение об ошибке ясное - то, что вы делаете, использует VLA, и они были добавлены в C99 и не являются частью C90. Следовательно, вы не можете этого сделать. Вам придется вернуться к динамическому распределению массивов - malloc() и free().   -  person Jonathan Leffler    schedule 30.03.2020
comment
Почему можно использовать только ... -ansi?   -  person Keith Thompson    schedule 30.03.2020
comment
Или, Почему нельзя использовать стандартный C (из этого века)? Если вы посещаете класс, который требует преподавания C89, вам нужно найти другой класс.   -  person rici    schedule 30.03.2020


Ответы (2)


product L[n1];  // line of the error

Эта строка определяет массив переменной длины. То есть массив, размер которого неизвестен во время компиляции. Эта функция не была добавлена ​​в язык C до версии C99, но флаг -ansi GCC указывает на использование правил из более старой версии языка C90.

В более старых версиях языка C вы можете использовать нестандартные функции платформы, такие как alloca (не делайте этого, если вы действительно не знаете, что делаете) или использовать _4 _ / _ 5_ для сделать динамическое распределение памяти:

product* L = malloc(n1 * sizeof(product));
// ...
free(L);
person Miles Budnek    schedule 30.03.2020
comment
Или просто объявите массив максимального размера, который вам понадобится. Если кто-то знает, каков максимальный размер, и знает, что всегда будет достаточно места в стеке для размещения любого размера массива, который он будет использовать, в большинстве случаев можно просто объявить массив максимального размера, который может потребоваться. Единственный сценарий, при котором это не удастся, но VLA будет работать, - это если функция иногда используется в обстоятельствах, когда массив будет большим, но доступно много стека, а иногда и в обстоятельствах, когда доступен небольшой стек, но массив будет маленький. На самом деле, довольно редко. - person supercat; 31.03.2020

Вместо этого используйте правильный динамический массив. Нравится:

product *L = malloc(n1 * sizeof(product));

Не забудьте освободить его после завершения использования (в конце функции):

free(L);

person numzero    schedule 30.03.2020