引入
auto是C语言的一个关键字,关键字主要用于声明变量的生存期为自动,即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量。这个关键字不怎么多写,因为所有的变量默认就是auto的。
C语言中提供了存储说明符auto,register,extern,static说明的四种存储类别。四种存储类别说明符有两种存储期:自动存储期和静态存储期。其中auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块是被建立,它在该程序块活动时存在,退出该程序块时撤销。
语言中包括了关键字auto,它可用于定义局部变量。但自从所有的非全局变量的缺省值假定为auto以来,auto就几乎很少使用了。 在C或者以前的C 中,auto关键字基本上可以被无视:比如这个局部变量:int a = 100;auto int a = 100;并没有什么区别。
但是在VC2010中,auto已经有了新的含义,它可以对类型进行推断使得我们在使用的时候可以这样auto a = 100;那么a就是int类型,初始值为100。
C语言中的auto关键字
C语言和C 中auto关键字的使用有很大区别。在C语言中使用auto关键字声明一个变量为自动变量,是C语言中应用最广泛的一种类型,在函数内定义变量时,如果没有被声明为其他类型的变量都是自动变量,也就是说,省去类型说明符auto的都是自动变量。这里的其他类型指的是变量的存储类型即:静态类型变量(static )、寄存器类型变量(register)和外部类型变量(extern)。例如:
代码语言:javascript复制void Test()
{
auto int x = 10; //定义自动变量x,auto可以省略
int y; //y和z都为自动变量,如果省略了auto 关键字则隐含表示为auto类型
double z;
...
}
在C语言中使用auto定义的变量可以不予初始化,但在C 中必须初始化。自动变量,在函数调用时分配存储空间,当完成调用是释放存储空间。当然也存在下面这种形式:
代码语言:javascript复制auto val; //当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型
为了说明当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型,可以看下面的代码:
代码语言:javascript复制#include <stdio.h>
#include <Windows.h>
int main()
{
double value1 = 3.2, value2 = 3.5;
/*使用auto 定义一个变量,在C语言中可以不初始化,编译器会使用一个随机值
值初始化变量val,但建议在写代码时进行初始化,为了说明与C 中的不同,这里
不予初始化*/
auto val;
val = value1 value2;
printf("%dn", val);
system("pause");
return 0;
}
通过调试监视窗口,观察变量的值的变化,来进行验证。
可以看到,进入程序,当执行过double value1 = 3.2, value2 = 3.5;语句后value1和value2被初始化为3.2和3.5,在调试过过程中编译器把auto value;当声明处理,跳过了该语句,可以通过类型观察到val的数据类型一直为int 执行完求和语句val = value value2;后,其结果为整形数据6。所以,C语言中,当省略了数据类型,则使用auto关键字修饰的变量默认为int 型数据。
C 中的auto关键字
C 中的auto关键字是一个类型说明符,通过变量的初始值或者表达式中参与运算的数据类型来推断变量的类型。编程时通常需要把表达式值式赋给变量,这就要求在声明变量时清楚的知道表达式的类型,C 11新标准引入了auto 类型说明符,让编译器去分析表达式的类型。由于,需要编译器推断变量或表达式的类型,所以,auto定义的变量必须初始化。例如:
代码语言:javascript复制auto val = 5.2f; //编译器会根据初始化的值来推断val的数据类型为flaot,但要注意如果去掉f则编译器会认为val double型变量
auto x = y z; //x初始化为y和z相加的结果,由y和z的数据类型推断x的数据类型
auto num; //但如果在C 中出现这样的语句,会编译报错,提示“类型包含“auto符号”必须具有初始值设定项”
使用auto也能在一条语句中声明多个变量。因为一条语句声明时只能有一种基本数据类型,所以该语句中的所有变量初始基本数据类型必须一样,例如:
代码语言:javascript复制auto i = 0, *p = &i; //正确:i是整数、p是整形指针
auto sz = 0, pi = 3, 14; //错误:sz和pi的类型不一致
auto和decltype 的作用有点相似,都可以推断某个表达式的具体类型,当我们希望从表达式的值推断出要定义的变量的类型,但不想用该表达式的值初始化变量时,可以使用decltype,作用是选择并返回操作数的数据类型,但并不计算表达式的值。如果decltype 使用的表达式不是一个变量,则decltype返回表达式结果对用的类型,”如果我们仅仅是想根据初始值确定一个变量合适的数据类型,那么auto是最佳人选。而只有当我们需要推断某个表达式的数据类型,并将其作为一种新的数据类型重复使用(比如,定义多个相同类型变量)或者单独使用(比如,作为函数的返回值类型)时,我们才真正需要用到decltype“。
在范围for语句中,经常会使用到auto关键字,正如文章开篇举得那个例子,范围for语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作。其语法形式为:
代码语言:javascript复制/*
*declaration 部分定义一个变量,该变量用于访问序列中的基础元素,expression部分是一个对象,用于表示
*一个序列。每次迭代,declaration部分的变量会初始化为expression部分的下一个元素值,statment是对字
*符的操作语句
*/
for (declaration : expression)
{
statement
}
下面看一个例子,将上面介绍到的关键字和范围for语句梳理一下:
代码语言:javascript复制//编写一段程序,使用范围for语句将字符串内的所有字符用‘X’代替
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin, str); //从输入中读取一行赋值给str1
//auto 是一个类型说明符,通过变量的初始值来判断变量的类型
for (auto &c : str) //对于字符串str中的每一个c
{
//decltype 类型指示符,选择并返回操作数的数据类型,如果decltype使用
//的表达式不是一个变量,则decltype返回表达式结果对应的类型
for (decltype(str.size()) index = 0; index < str.size(); index)
{
str[index] = 'X';
}
}
cout << str << endl; //打印替换后的字符串
system("pause");
return 0;
}
简单分析:上面的代码完成的功能是,把字符串中的所有字符‘X’用代替。先 从键盘读取一行字符串,然后使用范围for语句对其进行处理,在范围for语句中使用auto关键字推断变量c的数据类型,因为要改变字符串中的字符,所以将循环变量C定义为引用类型,然后使用for循环依次处理字符串str中的字符,将其修改为字符‘X’,在使用下标处理字符串中的字符是,我们需要知道字符串的长度,c 中的size()函数用于返回字符串的长度,即:字符串中字符的个数,类似于C语言中的strlen,字符串的下标从0开始,所以下标的取值大于等于0并且小于字符串的size()值,循环控制条件为:index < str.size(); 所以index为decltype(str.size())型的变量,这里使用decltype返回函数size()返回值类型,并且将其作为数据类型定义index作为字符串中字符的下标,(实际上size()返回的是一个size_t类型的值,个人认为,可以把 size_t 理解为unsigned int型),然后,在循环体内实现字符的替换,上面的代码中用到了本文中讲到的auto类型说明符,decltype类型指示符以及范围for语句,可以帮助我们简单的理解其简单应用。
【参考目录】
《C Prime》第五版
https://blog.csdn.net/qq_39779233/article/details/104207532