C语言 为什么auto a=1; 用C编译?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23406212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does auto a=1; compile in C?
提问by lee77
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 onlyin C++ since C++11, where it means that the type is deduced from the initializer.
当文件具有 .c 扩展名时,MS Visual Studio 2012 编译器编译时不会出错。我一直认为,当你使用.c扩展名时,编译应该按照C语法,而不是C++。此外,据我所知,自 C++11 以来,仅在 C++ 中才允许没有类型的 auto ,这意味着该类型是从初始值设定项中推导出来的。
Does that mean that my compiler isn't sticking to C, or is the code actually correct in C-language?
这是否意味着我的编译器没有坚持使用 C,或者代码在 C 语言中实际上是否正确?
回答by Fred Foo
autois an old C keyword that means "local scope". auto ais 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 ain this example.
auto是一个旧的 C 关键字,意思是“本地范围”。auto a与 相同auto int a,并且由于局部作用域是在函数内声明的变量的默认值,因此它也与int a本示例中的相同。
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 autoor extrn[sic]. C inherited the "everything is int" as a default rule, so you could declare integers with
这个关键字实际上是 C 的前身 B 的遗留物,其中没有基本类型:一切都是int,指向int,数组的int.(*) 声明将是auto或extrn[原文如此]。C 继承了“一切都是int”作为默认规则,因此您可以声明整数
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
ISO C 摆脱了这一点,但许多编译器仍然接受它以实现向后兼容性。如果它看起来不熟悉,那么您应该意识到相关规则在起作用
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.)
C++11 重用了关键字,如果有的话,很少有 C++ 程序员使用它的原始含义来进行类型推断。这在很大程度上是安全的,因为intC++98 中已经删除了 C 中的“一切都是”规则;唯一中断的是auto T a,无论如何都没有人使用。(在他关于语言历史的论文中,Stroustrup 对此发表了评论,但我现在找不到确切的参考资料。)
(*) String handling in B was interesting: you'd use arrays of intand pack multiple characters in each member. B was actually BCPLwith different syntax.
(*) B 中的字符串处理很有趣:您将int在每个成员中使用和打包多个字符的数组。B 实际上是具有不同语法的BCPL。
回答by David Hammen
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.
这既是对不的回答也是对不的扩展评论,自 1999 年以来这不是合法的 C。没有像样的现代 C 编译器允许这样做。
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.
是的,auto a=1;在 C1999(以及 C2011)中是非法的。仅仅因为现在这是非法的并不意味着现代 C 编译器应该拒绝包含此类构造的代码。我认为恰恰相反,一个体面的现代 C 编译器必须仍然允许这一点。
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;.
在针对 1999 或 2011 版本的标准编译问题中的示例代码时,clang 和 gcc 都是这样做的。两个编译器都会发出诊断信息,然后继续执行,就好像令人反感的陈述是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).
在我看来,这是一个体面的编译器应该做的。通过发布诊断,clang 和 gcc 完全符合标准。该标准并未规定编译器必须拒绝非法代码。该标准只是说,如果翻译单元包含违反任何语法规则或约束(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=1as if it were auto int a=1when the compiler is used in C90 or K&R mode.
给定包含非法构造的代码,任何体面的编译器都会尝试理解非法代码,以便编译器可以找到代码中的下一个错误。在第一个错误处停止的编译器不是一个很好的编译器。有一种方法可以理解auto a=1,那就是应用“隐式 int”规则。此规则强制编译器auto a=1按照auto int a=1在 C90 或 K&R 模式下使用编译器时进行解释。
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).
大多数编译器通常会拒绝包含非法语法的代码(拒绝:拒绝生成目标文件或可执行文件)。在这种情况下,编译器作者认为编译失败不是最佳选择。最好的办法是发出诊断信息,修复代码,然后继续。有太多的遗留代码充满了诸如register a=1;. 编译器应该能够在 C99 或 C11 模式下编译该代码(当然还有诊断)。
回答by BoBTFish
autohas a meaning in Cand 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., staticlifetime, where a variable lasts "forever", regardless of the scope. autois the default lifetime, and is almost never spelled out explicitly. This is why it was safe to change the meaning in C++.
auto在 2011 标准中C及C++之前具有含义。这意味着变量具有自动生命周期,即由作用域决定的生命周期。这与例如static生命周期相反,在生命周期中,无论范围如何,变量都“永远”持续。auto是默认生命周期,几乎从未明确说明。这就是为什么可以安全地更改 中的含义C++。
Now in C, prior to the 99 Standard, if you don't specify the type of a variable, it defaults to int.
现在在C99 标准之前,如果不指定变量的类型,则默认为int。
So with auto a = 1;you are declaring (and defining) an intvariable, with lifetime determined by the scope.
因此,auto a = 1;您正在声明(并定义)一个int变量,其生命周期由范围决定。
("lifetime" is more properly called "storage duration", but I think that is perhaps less clear).
(“生命周期”更恰当地称为“存储持续时间”,但我认为这可能不太清楚)。
回答by Mike Seymour
In C, and historic dialects of C++, autois a keyword meaning that ahas 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.
在 C 和 C++ 的历史方言中,auto是a具有自动存储功能的关键字含义。由于它只能应用于局部变量,默认情况下是自动的,没有人使用它;这就是 C++ 现在重新利用关键字的原因。
Historically, C has allowed variable declarations with no type specifier; the type defaults to int. So this declaration is equivalent to
从历史上看,C 允许没有类型说明符的变量声明;类型默认为int. 所以这个声明等价于
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 -Wallor -Wimplicit-int, gives a warning:
我认为这在现代 C 中已被弃用(并且可能被禁止);但是一些流行的编译器默认使用 C90(我认为确实允许它),而且令人讨厌的是,只有在您特别要求时才启用警告。用gcc编译并且用指定C99 -std=c99,或使警告用-Wall或-Wimplicit-int,给出警告:
warning: type defaults to ‘int' in declaration of ‘a'
回答by Mike Seymour
In C, automeans the same thing registerdoes in C++11: it means that a variable has automatic storage duration.
在 C 中,auto意味着与registerC++11 中的相同:这意味着变量具有自动存储持续时间。
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.
而在 C99 之前的 C 中(微软的编译器既不支持 C99 也不支持 C11,尽管它可能支持其中的一部分),在许多情况下可以省略类型,默认为int.
It does not take the type from the initialiser at all. You just happened to pick an initialiser that's compatible.
它根本不从初始化程序中获取类型。您只是碰巧选择了一个兼容的初始化程序。
回答by UmNyobe
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 /TCoption.Then in this case it is what larsmans said (old C autokeyword). It might be compiled as C++ without you knowing.
Visual Studio 编译类型可在right click on file -> Properties -> C/C++ -> Advanced -> Compile As. 确保它被编译为C强制/TC选项。那么在这种情况下就是larsmans所说的(旧Cauto关键字)。它可能会在您不知情的情况下编译为 C++。
回答by Amir Saniyan
A storage class defines the scope (visibility) and life time of variables and/or functions within a C Program.
存储类定义了 C 程序中变量和/或函数的范围(可见性)和生命周期。
There are following storage classes which can be used in a C Program
有以下存储类可以在 C 程序中使用
auto
register
static
extern
autois the default storage class for all local variables.
auto是所有局部变量的默认存储类。
{
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.
上面的例子定义了两个具有相同存储类的变量。auto 只能在函数内使用,即局部变量。
intis default type for autoin below code:
int是auto以下代码中的默认类型:
auto Month;
/* Equals to */
int Month;
Below code is legal too:
下面的代码也是合法的:
/* Default-int */
main()
{
reurn 0;
}

