Код:
int main(void)
{
auto a=1;
return 0;
}
компилируется без ошибок компилятором MS Visual Studio 2012, если файл имеет расширение .c. Я всегда думал, что при использовании расширения .c компиляция должна выполняться в соответствии с синтаксисом C, а не C ++. Более того, насколько я знаю, auto без типа разрешен только в C ++, начиная с C ++ 11, где это означает, что тип выводится из инициализатора.
Означает ли это, что мой компилятор не придерживается C, или действительно ли код на C-языке правильный?
int
был удален из стандарта C в 1999 году.Ответы:
auto
- старое ключевое слово C, означающее "локальная область видимости".auto a
то же самоеauto int a
, что и, и поскольку локальная область видимости является значением по умолчанию для переменной, объявленной внутри функции, она также такая же, какint a
в этом примере.Это ключевое слово на самом деле осталось от предшественника C B, где не было базовых типов: все было
int
, указатель наint
, массивint
. (*) Объявления были бы либоauto
илиextrn
[sic]. C унаследовалint
правило «все есть » как правило по умолчанию, поэтому вы можете объявлять целые числа с помощьюISO C избавился от этого, но многие компиляторы все еще принимают его для обратной совместимости. Если это кажется вам незнакомым, то вы должны понимать, что соответствующее правило работает в
что до сих пор распространено в современном коде.
C ++ 11 повторно использовал ключевое слово, которое мало кто из программистов C ++ использовал с исходным значением, для вывода его типа. Это в основном безопасно, потому что
int
правило «все есть » из C уже было исключено в C ++ 98; единственное, что ломается, это тоauto T a
, что все равно никто не использовал. (Где-то в своих статьях по истории языка Страуструп комментирует это, но я не могу найти точную ссылку прямо сейчас.)(*) Обработка строк в B была интересной: вы должны использовать массивы
int
и упаковывать несколько символов в каждый член. На самом деле B был BCPL с другим синтаксисом.источник
-Werror
.Это и ответ, и расширенный комментарий к « Нет», это не разрешено для C с 1999 года. Ни один достойный современный компилятор C не позволяет этого.
Да,
auto a=1;
это незаконно в C1999 (а также C2011). То, что это теперь незаконно, не означает, что современный компилятор C должен отклонять код, содержащий такие конструкции. Я бы сказал с точностью до наоборот, что достойный современный компилятор C все же должен позволять это.И clang, и gcc делают это при компиляции примера кода в вопросе против версий стандарта 1999 или 2011 годов. Оба компилятора выдают диагностику, а затем продолжают работу, как если бы было ошибочное утверждение
auto int a=1;
.На мой взгляд, это то, что должен делать достойный компилятор. Выполняя диагностику, clang и gcc полностью соответствуют стандарту. В стандарте не говорится, что компилятор должен отклонять недопустимый код. Стандарт просто говорит, что соответствующая реализация должна выдавать по крайней мере одно диагностическое сообщение, если единица трансляции содержит нарушение любого синтаксического правила или ограничения (5.1.1.3).
Учитывая код, содержащий недопустимые конструкции, любой достойный компилятор попытается разобраться в недопустимом коде, чтобы компилятор мог найти следующую ошибку в коде. Компилятор, который останавливается при первой ошибке, не очень хороший компилятор. Есть способ разобраться в
auto a=1
этом - применить правило "неявного int". Это правило заставляет компилятор интерпретировать,auto a=1
как если бы он был,auto int a=1
когда компилятор используется в режиме C90 или K&R.Большинство компиляторов обычно отклоняют код (reject: отказ от создания объектного файла или исполняемого файла), который содержит недопустимый синтаксис. Это тот случай, когда авторы компилятора решили, что отказ от компиляции - не лучший вариант. Лучше всего выполнить диагностику, исправить код и продолжить. Слишком много унаследованного кода, приправленного такими конструкциями, как
register a=1;
. Компилятор должен уметь компилировать этот код в режиме C99 или C11 (конечно, с диагностикой).источник
-ffs-please-stop-allowing-constructs-from-some-previous-millennium
вариант компилятора, или, говоря более кратко,-fstrict-compliance
вариант. Ворчание на компилятор: «Когда я использовал -std = c11, я не ожидал, что этот древний K&R kruft будет компилироваться. На самом деле, я хотел, чтобы он не компилировался!»-std=c99
быть строже - это шаг в правильном направлении :)gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror
(это то, что я обычно использую, даже в коде из вопросов по SO), то вы довольно близко подходите к тому, что хотите. Я бы хотел, чтобы GCC по умолчанию использовал хотя бы-std=c99
и предпочтительно-std=c11
(или,-std=gnu11
скорее всего , они так и поступили бы), но до тех пор… Вы можете настроить эти параметры;-pedantic
,-Wshadow
,-Wold-style-declaration
И некоторые другие могут быть полезны, но это хороший стартовый набор опций.-pedantic-errors
auto
имеет значение в Стандарте 2011 г.C
иC++
до него. Это означает, что у переменной есть автоматическое время жизни, то есть время жизни, определяемое областью действия . Это противоположно, например, времениstatic
жизни, когда переменная существует «вечно», независимо от области действия.auto
- время жизни по умолчанию, и почти никогда не указывается явно. Вот почему было безопасно изменить значение вC++
.Теперь
C
, до стандарта 99, если вы не укажете тип переменной, по умолчанию будет использоваться значениеint
.Итак,
auto a = 1;
вы объявляете (и определяете)int
переменную, время жизни которой определяется областью видимости.(«время жизни» правильнее называть «продолжительностью хранения», но я думаю, что это, возможно, менее ясно).
источник
main
функции".auto
иstatic
это единственные две возможности. Я пытался написать свой ответ таким образом, чтобы он был ориентирован на спрашивающего, который, кажется, новичок вC++
(иC
), поэтому я немного замалчил детали. Может быть, это была плохая идея; они должны быть покрыты рано или поздно.int
материал удален из C с 1999 года.В C и исторических диалектах C ++
auto
это ключевое слово,a
имеющее автоматическое хранение. Поскольку его можно применять только к локальным переменным, которые по умолчанию автоматические, никто не использует его; вот почему в C ++ это ключевое слово изменилось.Исторически C допускал объявление переменных без спецификатора типа; по умолчанию используется тип
int
. Итак, это объявление эквивалентноЯ думаю, что это устарело (и, возможно, запрещено) в современном C; но некоторые популярные компиляторы по умолчанию используют C90 (что, я думаю, позволяет это), и, что досадно, включают предупреждения, только если вы их специально просите. Компиляция с помощью GCC и указание C99 с помощью
-std=c99
или включение предупреждения с помощью-Wall
или-Wimplicit-int
дает предупреждение:источник
В C
auto
означает то же самое, чтоregister
и в C ++ 11: это означает, что переменная имеет автоматическую продолжительность хранения.А в C до C99 (а компилятор Microsoft не поддерживает ни C99, ни C11, хотя может поддерживать его части) тип во многих случаях может быть опущен, где он будет по умолчанию
int
.Он вообще не берет тип из инициализатора. Вы просто случайно выбрали совместимый инициализатор.
источник
auto
иregister
имел точно такое же значение (ранее я отмечал, что существуют ограничения на получениеregister
адреса -квалифицированной переменной, но это было неверно для C ++).register
, хотя и не рекомендуется, на данный момент сохраняет свое старое значение.auto
в C означает то же, что иregister
в C ++, что он и делает (оба означают автоматическую продолжительность хранения и ничего больше).Тип компиляции Visual Studio доступен по адресу
right click on file -> Properties -> C/C++ -> Advanced -> Compile As
. Чтобы убедиться, что он скомпилирован как/TC
опция C force. Тогда в этом случае это то, что сказал ларсманс (староеauto
ключевое слово C ). Он может быть скомпилирован как C ++ без вашего ведома.источник
Класс хранения определяет область видимости и время жизни переменных и / или функций в программе C.
Существуют следующие классы хранения, которые можно использовать в программе C
auto
- класс хранения по умолчанию для всех локальных переменных.В приведенном выше примере определены две переменные с одним и тем же классом хранения. auto может использоваться только внутри функций, то есть локальных переменных.
int
является типом по умолчанию дляauto
кода ниже:Код ниже также допустим:
источник