为什么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 a
与auto int a
相同,因为局部作用域是在函数内部声明的variables的默认值,所以在本例中它也与int a
相同。
这个关键字实际上是C的前身B的剩余部分,没有基types:一切都是int
, int
指针, int
数组(*)声明可以是auto
或extrn
[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年标准之前在C
和C++
有意义。 这意味着一个variables具有自动生命周期,即由该范围决定的生命周期 。 这与例如static
生命期相反,其中variables持续“永远”,而不pipe范围如何。 auto
是默认的生命周期,几乎从不明确拼出。 这就是为什么改变C++
的意义是安全的。
现在在C
,在99标准之前,如果你没有指定variables的types,它默认为int
。
所以用auto a = 1;
你声明(和定义)一个int
variables,其生命周期由范围决定。
(“一生”更恰当地称为“存储期限”,但我认为这可能不太清楚)。
在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。
在下面的代码中, int
是auto
默认types:
auto Month; /* Equals to */ int Month;
下面的代码也是合法的:
/* Default-int */ main() { reurn 0; }