Why does auto a=1; compile in C?

The code:

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

gets compiled without errors by the MS Visual Studio 2012 compiler, when the file has the .c extension. I have always thought that when you use the .c extension, compilation should be according to the C syntax, and not C++. Moreover, as far as I know auto without a type is allowed only in C++ since C++11, where it means that the type is deduced from the initializer.

Does that mean that my compiler isn't sticking to C, or is the code actually correct in C-language?

36911 次浏览

auto is an old C keyword that means "local scope". auto a is the same as auto int a, and because local scope is the default for a variable declared inside a function, it's also the same as int a in this example.

This keyword is actually a leftover from C's predecessor B, where there were no base types: everything was int, pointer to int, array of int.(*) Declarations would be either auto or extrn [sic]. C inherited the "everything is int" as a default rule, so you could declare integers with

auto a;
extern b;
static c;

ISO C got rid of this, but many compilers still accept it for backward compatibility. If it seems unfamiliar, then you should realise that a related rule is at work in

unsigned d;  // actually unsigned int

which is still common in modern code.

C++11 reused the keyword, which few if any C++ programmers were using with the original meaning, for its type inference. This is mostly safe because the "everything is int" rule from C had already been dropped in C++98; the only thing that breaks is auto T a, which no-one was using anyway. (Somewhere in his papers on the history of the language, Stroustrup comments on this, but I can't find the exact reference right now.)

(*) String handling in B was interesting: you'd use arrays of int and pack multiple characters in each member. B was actually BCPL with different syntax.

In C, auto means the same thing register does in C++11: it means that a variable has automatic storage duration.

And in C prior to C99 (and Microsoft's compiler does not support either C99 or C11, although it may support parts of it), the type can be omitted in many cases, where it will default to int.

It does not take the type from the initialiser at all. You just happened to pick an initialiser that's compatible.

auto has a meaning in C and C++ prior to the 2011 Standard. It means that a variable has automatic lifetime, that is, lifetime determined by the scope. This is opposed to, e.g., static lifetime, where a variable lasts "forever", regardless of the scope. auto is the default lifetime, and is almost never spelled out explicitly. This is why it was safe to change the meaning in C++.

Now in C, prior to the 99 Standard, if you don't specify the type of a variable, it defaults to int.

So with auto a = 1; you are declaring (and defining) an int variable, with lifetime determined by the scope.

("lifetime" is more properly called "storage duration", but I think that is perhaps less clear).

Visual studio compilation type is available at right click on file -> Properties -> C/C++ -> Advanced -> Compile As. To make sure it is compiled as C force /TC option.Then in this case it is what larsmans said (old C auto keyword). It might be compiled as C++ without you knowing.

In C, and historic dialects of C++, auto is a keyword meaning that a has automatic storage. Since it can only be applied to local variables, which are automatic by default, no-one uses it; which is why C++ has now repurposed the keyword.

Historically, C has allowed variable declarations with no type specifier; the type defaults to int. So this declaration is equivalent to

int a=1;

I think this is deprecated (and possibly forbidden) in modern C; but some popular compilers default to C90 (which, I think, does allow it), and, annoyingly, only enable warnings if you specifically ask for them. Compiling with GCC and either specifying C99 with -std=c99, or enabling the warning with -Wall or -Wimplicit-int, gives a warning:

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

This is both an answer and an extended comment to No, this isn't legal C since 1999. No decent modern C compiler allows for this.

Yes, auto a=1; is illegal in C1999 (and also C2011). Just because this is now illegal does not mean that a modern C compiler should reject code that contains such constructs. I would argue exactly the opposite, that a decent modern C compiler must still allow for this.

Both clang and gcc do just that when compiling the sample code in the question against the 1999 or 2011 versions of the standard. Both compilers issue a diagnostic and then carry on as if the objectionable statement had been auto int a=1;.

In my opinion, this is what a decent compiler should do. By issuing a diagnostic, clang and gcc are full compliant with the standard. The standard does not say that a compiler must reject illegal code. The standard merely says that a conforming implementation must produce at least one diagnostic message if a translation unit contains a violation of any syntax rule or constraint (5.1.1.3).

Given code that contains illegal constructs, any decent compiler will try to make sense of the illegal code so that the compiler can find the next error in the code. A compiler that stops at the first error isn't a very good compiler. There is a way to make sense out of auto a=1, which is to apply the "implicit int" rule. This rule forces the compiler to interpret auto a=1 as if it were auto int a=1 when the compiler is used in C90 or K&R mode.

Most compilers typically do reject code (reject: refuse to generate an object file or an executable) that contains illegal syntax. This is a case where the compiler authors decided that failing to compile is not the best option. The best thing to do is to issue a diagnostic, fix the code, and carry on. There's just too much legacy code that is peppered with constructs such as register a=1;. The compiler should be able to compile that code in C99 or C11 mode (with a diagnostic, of course).

A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.

There are following storage classes which can be used in a C Program

auto
register
static
extern

auto is the default storage class for all local variables.

{
int Count;
auto int Month;
}

The example above defines two variables with the same storage class. auto can only be used within functions, i.e. local variables.

int is default type for auto in below code:

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

Below code is legal too:

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