繁体   English   中英

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

[英]Why does auto a=1; compile in C?

代码:

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

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

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

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

这个关键字实际上是选自C的前身B,那里没有基本类型的后遗症:一切int ,指针int ,的阵列int (*)声明将是任一。 autoextrn [原文如此]。 C继承了“everything is int ”作为默认规则,因此您可以使用声明整数

auto a;
extern b;
static c;

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

unsigned d;  // actually unsigned int

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

C ++ 11重用了关键字,这个关键字很少,如果有任何C ++程序员使用它的原始含义,它的类型推断。 这大多是安全的,因为C中的“一切都是int ”规则已经在C ++ 98中被删除了; 唯一突破的是auto T a ,无论如何都没有人使用。 (在他关于语言历史的论文中 ,Stroustrup对此进行了评论,但我现在找不到确切的参考。)

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

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

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

clang和gcc都是在根据1999或2011版本的标准编译问题中的示例代码时做的。 两个编译器都发出一个诊断,然后继续进行,好像令人反感的语句是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模式编译该代码(当然还有诊断)。

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

现在在C ,在99 Standard之前,如果你没有指定变量的类型,它默认为int

所以使用auto a = 1; 你声明(并定义)一个int变量,生命周期由范围决定。

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

在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’

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

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

它根本不采用初始化器的类型。 你碰巧选择了兼容的初始化程序。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM