为什么auto a = 1; 在C编译?

代码:

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

当文件具有.c扩展名时,由MS Visual Studio 2012编译器编译时没有错误。 我一直认为,当你使用.c扩展名时,编译应该按照C语法,而不是C ++。 此外,据我所知,没有types的auto 只能在C ++ 11以后的C ++中使用,这意味着types是从初始化器中推导出来的。

这是否意味着我的编译器不是坚持C,还是C语言中的代码实际上是正确的?

auto是一个旧的C关键字,意思是“本地范围”。 auto aauto int a相同,因为局部作用域是在函数内部声明的variables的默认值,所以在本例中它也与int a相同。

这个关键字实际上是C的前身B的剩余部分,没有基types:一切都是intint指针, int数组(*)声明可以是autoextrn [sic]。 Cinheritance了“一切都是int ”作为默认规则,所以你可以声明整数

 auto a; extern b; static c; 

ISO C摆脱了这一点,但许多编译器仍然接受它的向后兼容性。 如果看起来不熟悉,那么你应该认识到,一个相关的规则正在工作

 unsigned d; // actually unsigned int 

这在现代代码中仍然很常见。

C ++ 11重新使用了关键字,对于其types推断,很less有C ++程序员使用原来的意思。 这大多是安全的,因为C中的“一切都是int ”规则已经被C ++ 98丢弃了; 唯一中断的是auto T a ,这是没人用的。 (在他关于语言历史的论文中 ,Stroustrup对此有所评论,但我现在还找不到确切的参考资料。)

(*)B中的string处理很有趣:你可以使用int数组,并在每个成员中包含多个字符。 B实际上是具有不同语法的BCPL 。

这既是一个答案,也是对No的一个扩展的评论,从1999年开始这不是合法的C语言。没有像样的现代C编译器可以做到这一点。

是的, auto a=1; 在C1999(也是C2011)中是非法的。 仅仅因为这现在是非法的,并不意味着一个现代的C编译器应该拒绝包含这样的结构的代码。 我认为恰恰相反,一个体面的现代C编译器必须仍然允许这样做。

在对1999或2011版标准的问题编译示例代码时,clang和gcc都是这样做的。 两个编译器都会发出一个诊断信息,然后继续进行,仿佛这个令人反感的语句是auto int a=1;

在我看来,这是一个体面的编译器应该做的。 通过发布诊断信息,clang和gcc完全符合标准。 标准并没有说编译器必须拒绝非法代码。 该标准只是说,如果翻译单元违反任何语法规则或约束(5.1.1.3),则相符的实现必须产生至less一条诊断消息。

给定包含非法构造的代码,任何体面的编译器都会尝试理解非法代码,以便编译器可以在代码中find下一个错误。 停止在第一个错误的编译器不是一个很好的编译器。 有一种方法可以使auto a=1 ,即应用“implicit int”规则。 编译器在C90或K&R模式下使用时,此规则强制编译器将auto a=1解释为auto int a=1

大多数编译器通常会拒绝包含非法语法的代码(拒绝:拒绝生成目标文件或可执行文件)。 编译器作者认为编译失败并不是最好的select。 最好的办法是发布诊断,修复代码,并继续。 有太多的遗留代码,如register a=1; 。 编译器应该能够在C99或C11模式下编译该代码(当然还有诊断)。

auto在2011年标准之前在CC++有意义。 这意味着一个variables具有自动生命周期,即由该范围决定的生命周期 。 这与例如static生命期相反,其中variables持续“永远”,而不pipe范围如何。 auto是默认的生命周期,几乎从不明确拼出。 这就是为什么改变C++的意义是安全的。

现在在C ,在99标准之前,如果你没有指定variables的types,它默认为int

所以用auto a = 1; 你声明(和定义)一个intvariables,其生命周期由范围决定。

(“一生”更恰当地称为“存储期限”,但我认为这可能不太清楚)。

在C和C ++的历史方言中, auto是一个关键词,意思是说a自动存储。 由于它只能应用于默认为自动的局部variables,所以没有人使用它; 这就是为什么C ++现在已经改变了关键字的原因。

历史上,C允许variables声明没有types说明符; types默认为int 。 所以这个声明等同于

 int a=1; 

我认为这在现代C中已被废弃(可能被禁止) 但是一些stream行的编译器默认为C90(我认为,它确实允许),令人讨厌的是,只有在你特别要求的时候才启用警告。 使用GCC进行编译,并使用-std=c99指定C99,或者使用-Wall-Wimplicit-int启用警告, -Wimplicit-int发出警告:

 warning: type defaults to 'int' in declaration of 'a' 

在C语言中, auto表示C ++ 11中同样的事情register :它意味着一个variables具有自动存储持续时间。

而在C99之前的C语言(微软的编译器不支持C99或C11,虽然它可能支持其中的一部分),但在许多情况下,这种types可以省略,默认为int

它根本不采用初始化程序的types。 你只是碰巧select一个兼容的初始化程序。

Visual studio编译types是可用的right click on file -> Properties -> C/C++ -> Advanced -> Compile As 。 为了确保它被编译为C force /TC选项。那么在这种情况下,就是学习者所说的(旧的C auto关键字)。 它可能会被编译为C ++而不知道。

存储类定义C程序中variables和/或函数的作用域(可见性)和生存时间。

有以下存储类可以在C程序中使用

 auto register static extern 

auto是所有本地variables的默认存储类。

 { int Count; auto int Month; } 

上面的例子定义了两个具有相同存储类的variables。 auto只能在函数内使用,即局部variables。

在下面的代码中, intauto默认types:

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

下面的代码也是合法的:

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