C auto关键字在哪里使用?


104

在大学时代,我读到了有关auto关键字的信息,但随着时间的流逝,我实际上忘记了它的含义。它定义为:

将局部变量定义为具有局部生存期

我从来没有发现它在任何地方都在使用,它真的被使用过吗?

Answers:


90

auto是类似的修饰符static。它定义了变量的存储类。但是,由于局部变量的默认值为auto,因此通常不需要手动指定它。

此页面列出了C中的不同存储类别。


13
在有人投票赞成我的答案之后,我只是再次看着这个。您说“通常不需要手动指定它”。我只想问:实际上是否存在auto 可以指定但默认情况下不会发生的情况?
杰里·科芬

2
@JerryCoffin不在C中。在C ++ 11中,它已被重新利用,您可以使用它来有效地获取局部变量类型推断。
2013年

2
一种可能的用法是在GNU C中向前声明嵌套函数-尽管这是对的原始定义的劫持autotigcc.ticalc.org/doc/keywords.html#auto
西亚

2
链接的页面已过时。自C11起,还有_Thread_local更多详细信息:en.cppreference.com/w/c/language/storage_durationstackoverflow.com/a/14289720/6557621
MCCCS

132

如果您阅读了IAQ(不常见问题)列表,您会知道auto主要用于定义或声明车辆:

auto my_car;

始终停在户外的车辆:

extern auto my_car;

对于那些缺乏幽默感并且想要“只是事实的女士”的人:简短的回答是,根本没有任何理由要使用auto。唯一允许您使用auto的变量是已经具有auto存储类的变量,因此您只是指定了无论如何都会发生的事情。尝试auto在没有auto存储类的将导致编译器拒绝您的代码。我想如果您想获得技术知识,则您的实现不必是编译器(而是编译器),并且从理论上讲,它可以在发出诊断后继续编译代码(但事实并非如此)。

kaz的小附录:

还有:

static auto my_car;

这需要根据ISO C进行诊断。这是正确的,因为它声明汽车已损坏。诊断是免费的,但是关闭仪表板灯将花费您80美元。(如果您从eBay购买了用于板载诊断的USB加密狗,则不超过20个)。

前面提到的extern auto my_car还需要进行诊断,因此,除负责停车执法的市政人员外,它永远不会通过编译器运行。

如果您extern static auto ...在任何代码库中都看到很多内容,则说明您处于困境中。在整个地方变成Rust之前,立即寻找更好的工作。


@self。:ISO似乎不知道“ ISO 2011”。您认为它可能会标准化吗?
杰里·科芬2014年

6
我的嘴巴没有咖啡,可乐,黑啤酒或其他深色液体,这是一件好事。在这种情况下,您应该欠我一个电脑屏幕@JerryCoffin。有史以来最好的答案!
David Hammen

2
@丹:说实话,您花了“一段时间”来阅读5行文本,并得到其中说的部分:“简短的回答是,根本没有任何理由要使用自动”?认真吗 鉴于您之前的评论,似乎至少有人认为它是积极的贡献。
杰里·科芬

@JerryCoffin我已经解释了,再次阅读我的评论。后见之明是20/20。
Dan Bechard

2
我最近通过了一场严重的大火(关闭了两条车道),这表明有必要char auto my_car;
形成鲜明

46

auto关键字是在C语言中无用。之所以这样,是因为在C语言之前,存在一种B语言,其中使用该关键字来声明局部变量是必需的。(B被开发为NB,后来成为C)。

这是B参考手册

如您所见,手册中包含大量示例auto。之所以如此,是因为没有int关键字。需要使用某种关键字来说“这是变量的声明”,并且该关键字还指示它是局部变量还是外部变量(autoextrn)。如果您不使用任何一个,则将出现语法错误。也就是说,x, y;它本身不是声明,而是声明auto x, y;

由于在开发语言时必须将用B编写的代码库移植到NB和C上,因此该语言的较新版本带来了一定的负担,从而提高了向后兼容性,从而减少了工作量。在的情况下auto,程序员不必搜寻每次出现的情况auto并将其删除。

从手册中可以明显看出,C中现在过时的“隐式int”残骸(能够在前面main() { ... }不写任何东西int)也来自B。这是支持B代码的另一种向后兼容性功能。函数没有在B中指定的返回类型,因为没有类型。一切都是一个字,就像许多汇编语言一样。

注意如何声明一个函数extrn putchar,然后唯一使它成为标识符使用的函数:它用于函数调用表达式中,如putchar(x),这就是告诉编译器将该无类型字视为函数指针的原因。


24

C语言auto中的关键字指示变量在块本地。由于这是块作用域变量的默认值,因此它是不必要且很少使用的(我认为我从未见过在讨论该关键字的文本示例中使用它)。如果有人可以指出auto需要使用以获得正确的解析或行为的情况,我会很感兴趣。

但是,在C ++ 11标准中,auto关键字已被“劫持”以支持类型推断,其中变量的类型可以从其初始值设定项的类型中获取:

auto someVariable = 1.5;   // someVariable will have type double

添加类型推断主要是为了支持在模板中声明变量或从模板函数中返回,在这些函数中,基于模板参数的类型(或在实例化模板时由编译器推导的类型)通常很难手动声明。


1
“变量是块的局部变量” —完全不正确。在块中声明的所有变量都是该块的局部变量(相对于作用域)。它们可能链接到程序中的其他变量,但是声明仅在该块中可见。 auto与存储类无关,它与可见性无关。
fuz

12

使用旧的Aztec C编译器,可以使用命令行开关将所有自动变量转换为静态变量(以提高寻址速度)。

但是auto在这种情况下,显式声明为的变量将保持原样。(必须具有递归函数,否则递归函数将无法正常工作!)


7

auto关键字类似于在Python中包含分号,以前的语言(B)要求使用该关键字,但是开发人员意识到它是多余的,因为大多数情况是auto

我怀疑它留给了从B到C的过渡。简而言之,一种用途是与B语言兼容。

例如在B和80年代C:

/* The following function will print a non-negative number, n, to
   the base b, where 2<=b<=10.  This routine uses the fact that
   in the ASCII character set, the digits 0 to 9 have sequential
   code values.  */

printn(n, b) {
        extrn putchar;
        auto a;

        if (a = n / b)        /* assignment, not test for equality */
                printn(a, b); /* recursive */
        putchar(n % b + '0');
}

1

Auto关键字是一个存储类(决定变量和存储位置生存期的某种技术)。它具有这样一种行为,即该关键字的Help所创建的变量的寿命(lifetime)仅驻留在花括号内

{
    auto int x=8;        
    printf("%d",x);  // here x is 8

    { 
        auto int x=3;
        printf("%d",x);  // here x is 3
    }              

    printf("%d",x);  // here x is 8
}          

0

auto只能用于块作用域变量。extern auto int之所以是垃圾,是因为编译器无法确定它是使用外部定义还是使用自动定义覆盖extern(auto和extern的存储持续时间完全不同,例如static auto int,这显然也是垃圾)。它总是可以选择以一种方式解释它,而是选择将其视为错误。

auto确实提供了一个功能,并且启用了功能内的“一切都是整数”规则。与函数外部不同,在函数内部将错误a=3解释为定义,int a =3因为赋值在文件作用域中不存在,这a=3是函数内部的错误,因为显然编译器始终将其解释为对外部变量的赋值,而不是对定义的赋值(即使存在没有extern int a在功能上还是在文件范围内向前声明),但像符staticconstvolatileauto将意味着这是一个定义和编译器把它作为一个定义,但auto没有其他说明符的副作用。auto a=3因此是隐式的auto int a = 3。诚然,signed a = 3具有相同的效果,unsigned a = 3并且始终是unsigned int。

还要注意“ auto对是否将对象分配给寄存器没有影响(除非某些特定的编译器对此有所注意,但这似乎不太可能)”


-1

我确定您熟悉C中的存储类说明符,即“ extern”,“ static”,“ register”和“ auto”。其他答案中几乎给出了“ auto”的定义,但是我不确定“ auto”关键字的可能用法,但我认为它取决于编译器。您会看到,关于存储类说明符,有一条规则。我们不能为变量使用多个存储类说明符。这就是为什么静态全局变量不能被外部化的原因。因此,它们仅对文件已知。进入编译器设置时,可以启用速度优化标记。编译器优化的方法之一是 它查找没有存储类说明符的变量,然后根据高速缓存的可用性和其他一些因素进行评估,以查看是否应使用寄存器说​​明符来处理该变量。现在,如果我们想优化代码以提高速度,同时又知道程序中的特定变量不是很重要,那么我们甚至不希望编译器将其视为寄存器。我虽然输入了auto,但是由于键入“ register auto int a;”,编译器将无法向变量添加寄存器说明符。或“自动注册int a”;引发使用多个存储类说明符的错误。综上所述,我认为auto可以禁止编译器通过优化将变量视为寄存器。如果我们想优化代码以提高速度,同时又知道程序中的特定变量不是很重要,又不想编译器甚至将其视为寄存器,该怎么办?我虽然输入了auto,但是由于键入“ register auto int a;”,编译器将无法向变量添加寄存器说明符。或“自动注册int a”;引发使用多个存储类说明符的错误。综上所述,我认为auto可以禁止编译器通过优化将变量视为寄存器。如果我们想优化代码以提高速度,同时又知道程序中的特定变量不是很重要,又不想编译器甚至将其视为寄存器,该怎么办?我虽然输入了auto,但是由于键入“ register auto int a;”,编译器将无法向变量添加寄存器说明符。或“自动注册int a”;引发使用多个存储类说明符的错误。综上所述,我认为auto可以禁止编译器通过优化将变量视为寄存器。引发使用多个存储类说明符的错误。综上所述,我认为auto可以禁止编译器通过优化将变量视为寄存器。引发使用多个存储类说明符的错误。综上所述,我认为auto可以禁止编译器通过优化将变量视为寄存器。

该理论不适用于GCC编译器,但是我没有尝试过其他编译器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.