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

时间:2014-05-01 10:50:20

标签: c auto c11

代码:

int main(void)
{
    auto a=1;
    return 0;
}
当文件具有.c扩展名时,

在MS Visual Studio 2012编译器中编译时没有错误。我一直认为,当你使用.c扩展名时,编译应该是根据C语法,而不是C ++。此外,据我所知,自C ++ 11以来,只有 的C ++ 11允许auto不带类型,这意味着该类型是从初始化程序中推断出来的。

这是否意味着我的编译器不是坚持使用C,或者代码在C语言中是否真的正确?

7 个答案:

答案 0 :(得分:238)

auto是旧的C关键字,表示“本地范围”。 auto aauto int a相同,并且因为局部范围是函数内声明的变量的默认值,所以在此示例中它也与int a相同。

这个关键字实际上是C的前身B的遗留物,其中没有基类型:一切都是int,指向int的指针,int的数组。(*)声明会可以是autoextrn [原文如此]。 C继承了“一切都是int”作为默认规则,因此您可以使用

声明整数
auto a;
extern b;
static c;

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

中起作用
unsigned d;  // actually unsigned int

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

C ++ 11重用了关键字,这个关键字很少,如果有任何C ++程序员使用其原始含义,那么它的类型推断。这大多是安全的,因为C中的“一切都是int”规则已经在C ++ 98中删除了;唯一打破的是auto T a,无论如何都没有人使用。 (在papers on the history of the language的某个地方,Stroustrup对此发表评论,但我现在找不到确切的参考。)

(*)B中的字符串处理很有意思:你使用int的数组并在每个成员中打包多个字符。 B实际上是BCPL,语法不同。

答案 1 :(得分:35)

这是对的回答和扩展评论。不,自1999年以来这不是合法的C.没有像样的现代C编译器允许这样做。

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

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

在我看来,这是一个体面的编译器应该做的事情。通过发布诊断,clang和gcc完全符合标准。该标准并未说明编译器必须拒绝非法代码。该标准仅表示如果翻译单元包含违反任何语法规则或约束的情况,符合要求的实现必须至少生成一条诊断消息(5.1.1.3)。

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

大多数编译器通常拒绝包含非法语法的代码(拒绝:拒绝生成目标文件或可执行文件)。在这种情况下,编译器作者认为无法编译不是最佳选择。最好的办法是发布诊断,修复代码,然后继续。遗留下来的遗留代码太多了register a=1;等构造。编译器应该能够在C99或C11模式下编译该代码(当然还有诊断)。

答案 2 :(得分:29)

auto在2011标准之前的CC++中具有含义。这意味着变量具有自动生命周期,即lifetime determined by the scope。这与例如static寿命相反,其中变量持续"永远",无论范围如何。 auto是默认生命周期,几乎从未明确拼写过。这就是改变C++中的含义是安全的原因。

现在在C中,在99标准之前,如果您没有指定变量的类型,则默认为int

因此,使用auto a = 1;声明(并定义)int变量,其寿命由范围决定。

("生命周期"被更恰当地称为"存储持续时间",但我认为这可能不太清楚)。

答案 3 :(得分:8)

在C和C ++的历史方言中,auto是一个关键字,意味着a具有自动存储。因为它只能应用于默认情况下自动的局部变量,所以没有人使用它;这就是为什么C ++现在重新使用关键字。

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

int a=1;

我认为这在现代C中被弃用(并且可能被禁止);但是一些流行的编译器默认使用C90(我认为它确实允许它),并且,令人讨厌的是,如果您特别要求它们,则仅启用警告。使用GCC进行编译并使用-std=c99指定C99,或使用-Wall-Wimplicit-int启用警告,会发出警告:

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

答案 4 :(得分:5)

在C中,auto表示{C} 11中register的作用相同:它表示变量具有自动存储持续时间。

在C99之前的C中(并且Microsoft的编译器不支持C99或C11,虽然它可能支持它的一部分),但在许多情况下可以省略类型,它将默认为int

根本不需要来自初始化程序的类型。你碰巧选择了兼容的初始化器。

答案 5 :(得分:3)

Visual Studio编译类型可在right click on file -> Properties -> C/C++ -> Advanced -> Compile As获得。为了确保它被编译为C force /TC选项。那么在这种情况下,它就是larsmans所说的(旧的C auto关键字)。它可能在你不知情的情况下被编译为C ++。

答案 6 :(得分:3)

存储类定义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;
}