Почему auto a = 1; компилировать в C?

Код:

int main(void)
{
    auto a=1;
    return 0;
}

скомпилируется без ошибок компилятором MS Visual Studio 2012, когда файл имеет расширение .c. Я всегда думал, что при использовании расширения .c компиляция должна соответствовать синтаксису C, а не С++. Более того, насколько я знаю, авто без типа допускается только в С++ с С++ 11, где это означает, что тип выводится из инициализатора.

Означает ли это, что мой компилятор не придерживается C, или это действительно правильный код на C-языке?

Ответ 1

auto - это старое ключевое слово C, которое означает "локальная область". auto a совпадает с auto int a, и поскольку локальная область является значением по умолчанию для переменной, объявленной внутри функции, она также совпадает с int a в этом примере.

Это ключевое слово на самом деле остается от C предшественника B, где не было базовых типов: все было int, указатель на int, массив int. (*) Объявления были бы либо auto, либо extrn [sic]. C наследует "все как int" как правило по умолчанию, поэтому вы можете объявлять целые числа с

auto a;
extern b;
static c;

ISO C избавился от этого, но многие компиляторы по-прежнему принимают его для обратной совместимости. Если это кажется незнакомым, тогда вы должны понять, что связанное правило работает в

unsigned d;  // actually unsigned int

который по-прежнему распространен в современном коде.

С++ 11 повторно использовало ключевое слово, которое несколько, если какие-либо программисты на C++ использовали с исходным значением, для его вывода типа. Это в основном безопасно, потому что правило "все есть int" из C уже было сброшено в С++ 98; единственное, что ломается, - это auto T a, которого никто в любом случае не использовал. (Где-то в его документах по истории языка, Stroustrup комментирует это, но я не могу найти точную ссылку прямо сейчас.)

(*) Обработка строк в B была интересной: вы использовали бы массивы int и добавляли несколько символов в каждом члене. B был фактически BCPL с различным синтаксисом.

Ответ 2

Это и ответ, и расширенный комментарий к No, это не является законным 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.

Большинство компиляторов обычно отклоняют код (отклоняют: отказываются генерировать объектный файл или исполняемый файл), который содержит незаконный синтаксис. Это случай, когда авторы компилятора решили, что компиляция не является лучшим вариантом. Лучше всего сделать диагностику, исправить код и продолжить. Там слишком много устаревшего кода, надутого конструкциями, такими как register a=1;. Компилятор должен иметь возможность компилировать этот код в режиме C99 или C11 (с диагностикой, конечно).

Ответ 3

auto имеет значение в C и C++ до стандарта 2011 года. Это означает, что переменная имеет автоматическое время жизни, то есть время жизни, определяемое областью. Это противоречит, например, static времени жизни, где переменная длится "навсегда", независимо от области действия. auto - это время жизни по умолчанию и почти не указано явно. Вот почему было безопасно изменить значение в C++.

Теперь в C, перед стандартом 99, если вы не укажете тип переменной, по умолчанию она будет int.

Итак, с помощью auto a = 1; вы объявляете (и определяете) переменную int со временем жизни, определяемым областью.

( "время жизни" более правильно называется "длительностью хранения", но я думаю, что это, возможно, менее понятно).

Ответ 4

В C и исторических диалектах С++ auto - это ключевое слово, означающее, что a имеет автоматическое хранилище. Поскольку он может применяться только к локальным переменным, которые по умолчанию автоматические, никто не использует его; поэтому С++ теперь перепрограммирует ключевое слово.

Исторически C допускал объявления переменных без спецификатора типа; тип по умолчанию равен int. Таким образом, это объявление эквивалентно

int a=1;

Я думаю, что это устарело (и, возможно, запрещено) в современном C; но некоторые популярные компиляторы по умолчанию используют C90 (что, я думаю, это разрешает), и, досадно, только активировать предупреждения, если вы специально их просите. Компиляция с помощью GCC и определение C99 с помощью -std=c99 или включение предупреждения с помощью -Wall или -Wimplicit-int дает предупреждение:

warning: type defaults to ‘int’ in declaration of ‘a’

Ответ 5

В C, auto означает ту же самую вещь register делает в С++ 11: это означает, что переменная имеет автоматическую продолжительность хранения.

И в C до C99 (и компилятор Microsoft не поддерживает ни C99, ни C11, хотя он может поддерживать его части), во многих случаях тип может быть опущен, где по умолчанию будет int.

Он не принимает тип от инициализатора вообще. Вам просто удалось выбрать инициализатор, совместимый.

Ответ 6

Тип компиляции Visual Studio доступен в right click on file -> Properties -> C/C++ -> Advanced -> Compile As. Чтобы убедиться, что он скомпилирован как опция C force /TC. Тогда в этом случае это то, что сказал ларсман (старое ключевое слово C auto). Он может быть скомпилирован как С++, если вы не знаете.

Ответ 7

Класс хранения определяет область видимости и время жизни переменных и/или функций в рамках программы C.

Существуют следующие классы хранения, которые могут использоваться в программе C

auto
register
static
extern

auto - это класс хранения по умолчанию для всех локальных переменных.

{
        int Count;
        auto int Month;
}

В приведенном выше примере определяются две переменные с одним и тем же классом хранения. auto может использоваться только внутри функций, то есть локальных переменных.

int - тип по умолчанию для auto в нижнем коде:

auto Month;
/* Equals to */
int Month;

Ниже приведен закон также:

/* Default-int */
main()
{
    reurn 0;
}