在我上大学的时候,我读到了这个auto
关键字,随着时间的推移,我实际上忘记了它是什么。它被定义为:
将局部变量定义为具有局部生命周期
我从来没有发现它在任何地方都被使用过,它真的被使用过吗?如果是这样,那么它在哪里使用以及在哪些情况下使用?
在我上大学的时候,我读到了这个auto
关键字,随着时间的推移,我实际上忘记了它是什么。它被定义为:
将局部变量定义为具有局部生命周期
我从来没有发现它在任何地方都被使用过,它真的被使用过吗?如果是这样,那么它在哪里使用以及在哪些情况下使用?
如果您阅读过IAQ(不常见问题)列表,您就会知道 auto 主要用于定义或声明车辆:
auto my_car;
一直停在户外的车辆:
extern auto my_car;
对于那些缺乏幽默感并且想要“只是事实女士”的人:简短的回答是根本没有任何理由使用auto
。唯一允许您使用auto
的是已经具有auto
存储类的变量,因此您只是指定了无论如何都会发生的事情。尝试auto
在没有auto
存储类的任何变量上使用将导致编译器拒绝您的代码。我想如果你想获得技术,你的实现不一定是编译器(但它是),理论上它可以在发出诊断后继续编译代码(但它不会)。
kaz的小附录:
还有:
static auto my_car;
这需要根据 ISO C 进行诊断。这是正确的,因为它声明汽车发生故障。诊断是免费的,但关闭仪表板灯将花费您 80 美元。(二十个或更少,如果您从 eBay 购买自己的用于车载诊断的 USB 加密狗)。
上述extern auto my_car
还需要诊断,因此它永远不会通过编译器运行,除非由负责停车执法的城市工作人员运行。
如果你在任何代码库中看到很多extern static auto ...
,那么你就在一个糟糕的社区;在整个地方转向 Rust 之前立即寻找更好的工作。
auto
是一个修饰符,如static
. 它定义了变量的存储类。但是,由于局部变量的默认值是auto
,因此您通常不需要手动指定它。
此页面列出了 C 中的不同存储类。
auto
关键字在 C 语言中是无用的。之所以存在,是因为在 C 语言之前存在 B 语言,其中该关键字是声明局部变量所必需的。(B发展成NB,变成C)。
这是B 的参考手册。
如您所见,手册中充斥着使用示例auto
。之所以如此,是因为没有int
关键字。需要某种关键字来表示“这是一个变量的声明”,并且该关键字还指示它是本地的还是外部的(auto
vs extrn
)。如果您不使用其中一个,则会出现语法错误。也就是说,x, y;
它本身不是一个声明,而是一个声明auto x, y;
。
由于在开发语言时必须将用 B 编写的代码库移植到 NB 和 C,因此该语言的较新版本带有一些包袱,以提高向后兼容性,从而减少工作量。在 的情况下auto
,程序员不必逐个查找auto
并删除它。
从手册中可以明显看出,C 中现在已经过时的“隐式 int”(能够在前面main() { ... }
没有任何内容的情况下编写int
)也来自 B。这是支持 B 代码的另一个向后兼容功能。函数没有在 B 中指定的返回类型,因为没有类型。一切都是一个词,就像在许多汇编语言中一样。
注意一个函数是如何被声明extrn putchar
的,然后是唯一使它成为标识符使用的函数的东西:它在函数调用表达式中使用,如putchar(x)
,这就是告诉编译器将该无类型单词视为函数指针的原因。
在 Cauto
中是一个关键字,表示变量是块的局部变量。由于这是块范围变量的默认值,因此它是不必要的并且很少使用(我认为我从未见过它在讨论关键字的文本中的示例之外使用)。如果有人能指出auto
需要使用 来获得正确的解析或行为,我会很感兴趣。
但是,在 C++11 标准中,auto
关键字已被“劫持”以支持类型推断,其中变量的类型可以从其初始值设定项的类型中获取:
auto someVariable = 1.5; // someVariable will have type double
添加类型推断主要是为了支持在模板中声明变量或从模板函数返回,其中基于模板参数(或在实例化模板时由编译器推导)的类型通常很难手动声明。
使用旧的 Aztec C 编译器,可以使用命令行开关将所有自动变量转换为静态变量(以提高寻址速度)。
但是在这种情况下,显式声明的变量auto
保持原样。(递归函数的必要条件,否则将无法正常工作!)
该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) {
extern putchar;
auto a;
if (a = n / b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n % b + '0');
}
auto
只能用于块范围的变量。extern auto int
是垃圾,因为编译器无法确定这是使用外部定义还是使用自动定义覆盖 extern(auto 和 extern 也是完全不同的存储持续时间,例如static auto int
,这显然也是垃圾)。它总是可以选择以一种方式解释它,而是选择将其视为错误。
有一个特性auto
确实提供了,那就是在函数内部启用“一切都是 int”规则。与函数外部不同,由于在文件范围内不存在赋值,因此 wherea=3
被解释为定义,这是函数内部的错误,因为显然编译器总是将其解释为对外部变量的赋值而不是定义(即使存在在函数或文件范围内没有前向声明),但是像,或or这样的说明符暗示它是一个定义,编译器将其作为定义,除了没有其他说明符的副作用。因此是隐含的。诚然,int a =3
a=3
extern int a
static
const
volatile
auto
auto
auto a=3
auto int a = 3
signed a = 3
具有相同的效果,并且unsigned a = 3
始终是无符号整数。
另请注意'auto
对是否将对象分配给寄存器没有影响(除非某些特定的编译器注意到它,但这似乎不太可能)'
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
}
我相信您熟悉 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 编译器,但是我没有尝试过其他编译器。