C: память стека, goto и «переход в область идентификатора с измененным типом»,

Я обнаружил, что это отказывается компилировать:

int test_alloc_stack(int size){ if(0) goto error; // same issue whatever conditional is used int apply[size]; give_values(apply,size); return 1; error: return 0; } 

Ошибка, которую я получаю: «перейти в область идентификатора с измененным типом». Ликвидация линии с «goto» и переход к ошибке решает проблемы.

Если я использую динамическое распределение для применения, проблема также исчезнет. Это компилирует штраф:

  int test_alloc_heap(int size){ if(0) goto error; int * apply = calloc(sizeof(int),size); give_values(apply,size); free(apply); return 1; error : return 0; } 

Что здесь происходит ?

Декларация:

 int apply[size]; 

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

Если вы переходите на динамическое распределение, инициализация и очистка становятся вашей ответственностью, а не компилятором.

Стандарт запрещен:

C99, пункт 6.8.6.1

Ограничения

[…] Оператор goto не должен выходить за пределы идентификатора, имеющего измененный тип, внутри области этого идентификатора.

Это именно то, что делает ваш goto , а именно: прыгать из-за пределов сферы apply внутри него.

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

 if(0) goto error; { int apply[size]; give_values(apply,size); return 1; } error: return 0; 

Ваш goto заставляет вас пропускать строку, которая распределяет apply (во время выполнения).

Вы можете решить проблему одним из четырех способов:

1: Перепишите свой код, чтобы вы не использовали goto.

2: Переместите декларацию о apply до goto .

3: Измените область действия, чтобы error: выходит за frameworks apply :

 int test_alloc_stack(int size){ if(0) goto error; // same issue whatever conditional is used { int apply[size]; give_values(apply,size); return 1; } error: return 0; } 

4: Измените объявление переменной, чтобы его размер можно было определить во время компиляции.