ISO C90 запрещает смешанные декларации и код в C

83

Я объявил переменную таким образом:

Получаю предупреждение:

ISO C90 запрещает смешанные декларации и код

Как я могу это исправить?

Питер Мортенсен
источник
2
Это похоже на GCC -pedanticили -std=c89, и в этом случае вы можете скомпилировать, -std=gnu99если хотите.
Дитрих Эпп
3
Если вы используете gcc, вы можете указать использование C99, который допускает смешанные объявления и код (флаг -std=c99).
hmjd 08
11
Один из вариантов - прекратить компиляцию по стандарту, которому 22 года, для которого даже была заменена замена.
Стивен Кэнон
5
@StephenCanon, сообщите об этом Microsoft. :)
hmjd 08
2
@hmjd: Microsoft не заинтересована в поставке компилятора C; это, скорее всего, не изменится. К счастью, существует ряд совершенно хороших компиляторов, ориентированных на платформу, поставляемую другими поставщиками.
Стивен Кэнон

Ответы:

127

Я думаю, вам следует переместить объявление переменной в начало блока. Т.е.

к

Йохан Котлински
источник
5
... или откройте новый контекст:{foo(); {int i=0; bar();}}
alk
3
@alk s / context / block Это то, что называется в стандарте C.
Jens
@Johan Kotlinski Но какое это имеет значение?
ocean800,
1
@ ocean800 В спецификации C90 сказано, что у вас не может быть объявлений после не-объявлений в одном блоке.
MM
37

Вплоть до стандарта C99 все объявления должны были стоять перед любыми операторами в блоке:

C99 позволяет смешивать объявления и операторы (например, C ++). Многие компиляторы по- прежнему по умолчанию C89, и некоторые компиляторы (например, от Microsoft) не поддерживают C99 вообще .

Итак, вам нужно будет сделать следующее:

  1. Определите, поддерживает ли ваш компилятор C99 или новее; если это так, настройте его так, чтобы он компилировал C99 вместо C89;

  2. Если ваш компилятор не поддерживает C99 или более позднюю версию, вам нужно будет либо найти другой компилятор, который поддерживает его, либо переписать код, чтобы все объявления располагались перед любыми операторами в блоке.

Джон Боде
источник
11

Просто используйте компилятор (или предоставьте ему необходимые аргументы), чтобы он компилировался для более новой версии стандарта C, C99 или C11. Например, для семейства компиляторов GCC это будет -std=c99.

Йенс Густедт
источник
6
Этот ответ в лучшем случае неполный. Это устраняет проблему, но не объясняет, что ее вызвало. Этот ответ исключает ситуации, когда более новый компилятор невозможен (несколько возможных причин ...) или среды сборки, в которых переключение параметров на компилятор, как это, невозможно. Голосование "против", потому что я не могу согласиться, что это "настоящий" ответ.
Эндрю Фаланга
1
В некоторых случаях -std=gnu89используется при компиляции модулей ядра Linux.
cbix
4

Убедитесь, что переменная находится в верхней части блока, и, если вы компилируете ее -ansi-pedantic, убедитесь, что она выглядит так:

Рон Нуни
источник
Вы по-прежнему можете инициализировать переменную, вы просто не можете разместить код до его объявления.
SS Anne
2

Чтобы определить, что действительно вызывает ошибку, я бы сначала попытался удалить = 0

  • Если произошла ошибка, то, скорее всего, объявление идет после кода.

  • Если ошибок нет, то это может быть связано с флагами принуждения / компиляции C-стандарта ИЛИ ... чем-то еще.

В любом случае объявите переменную в начале текущей области видимости. Затем вы можете инициализировать его отдельно. В самом деле, если эта переменная заслуживает отдельной области видимости - ограничьте ее определение в {}.

Если OP сможет прояснить контекст, то последует более направленный ответ.

vmsnomad
источник
1

-Wdeclaration-after-statement минимальный воспроизводимый пример

main.c

Предупредить:

Не предупреждать:

Предупреждение:

Проверено на Ubuntu 16.04, GCC 6.4.0.

Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник