黄浦网站设计,营口化工网站建设,云南住房建设厅网站,一个超链接 多个网站文章目录 #x1f35f;一、auto关键字#xff08;C11#xff09;#x1f369;1、auto的简介#x1f369;2、auto的使用细则#x1f6a9;auto与指针和引用结合起来使用#x1f6a9; 在同一行定义多个变量 #x1f369;3、auto不能推导的场景1️⃣auto不能作为函数的参数… 文章目录 一、auto关键字C111、auto的简介2、auto的使用细则auto与指针和引用结合起来使用 在同一行定义多个变量 3、auto不能推导的场景1️⃣auto不能作为函数的参数2️⃣auto不能直接用来声明数组 4、auto使用的注意事项 二、基于范围的for循环C111、范围for的语法2、范围for的使用条件1️⃣for循环迭代的范围必须是确定的2️⃣迭代的对象要实现和的操作 三、指针空值nullptrC11注意 一、auto关键字C11
1、auto的简介 在早期C/C中auto的含义是使用auto修饰的变量是具有自动存储器的局部变量但遗憾的是一直没有人去使用它大家可思考下为什么 C11中标准委员会赋予了auto全新的含义即auto不再是一个存储类型指示符而是作为一个新的类型指示符来指示编译器auto定义的变量的类型由变量定义和初始化语句等号的右边的值的类型决定auto声明的变量必须由编译器在编译时期推导而得 举个栗子看一下
int TestAuto()
{return 10;
}
int main()
{int a 10;auto b a;auto c a;auto d 8.6;auto e TestAuto();cout typeid(b).name() endl;cout typeid(c).name() endl;cout typeid(d).name() endl;cout typeid(e).name() endl;return 0;
}在这里我们要插入一个知识点 — typeid 操作符 typeid( x ).name() — 用来查看数据x实际数据类型 这里暂且不做过多介绍简单了解一下 程序运行结果 在面向对象的复杂编程中 有时我们很难确定一个表达式的返回值会是什么类型的这种时候就可以用auto声明的变量来接收表达式的值。还有些时候C编程中表达式的值是一些很复杂的自定义类型值这时也可以用auto声明的变量来接收表达式的值 比如如下场景
#include iostream
#include time.h
#include string
#include mapusing std::cout;
using std::endl;int main()
{std::mapstd::string, std::string m{ { apple, 苹果 }, { orange,橙子 },{pear,梨} };auto it m.begin(); 用auto声名的变量it来接收表达式的返回值while (it ! m.end()){//....}return 0;
}上面代码段中的std::mapstd::string, std::string就是一个复杂的类型m.begin()返回值就可以用auto声名的变量it来接收十分方便 typedef(类型重定义)也可以简化上述代码但是typedef用于重定义指针类型并用于声明变量时无法用const来保护指针所指向内存空间 因此typedef的使用也是由局限性相比之下auto的使用更方便灵活 2、auto的使用细则
auto与指针和引用结合起来使用 用auto声明指针类型时用auto和auto*没有任何区别但用auto声明引用类型时则必须加 举个栗子
int main()
{int x 10;auto a x;auto* b x;auto c x;cout a b c endl;cout typeid(a).name() endl;cout typeid(b).name() endl;cout typeid(c).name() endl;return 0;
}在同一行定义多个变量
先看下面这段代码
void TestAuto()
{auto a 1, b 2;auto c 3, d 4.0; // 该行代码会编译失败因为c和d的初始化表达式类型不同
}当在同一行声明多个变量时这些变量必须是相同的类型否则编译器将会报错因为编译器实际只对第一个类型进行推导然后用推导出来的类型定义其他变量 3、auto不能推导的场景
1️⃣auto不能作为函数的参数
// 此处代码编译失败auto不能作为形参类型因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{//...
}2️⃣auto不能直接用来声明数组
void TestAuto()
{int a[] {1,2,3};auto b[] {456};
}3️⃣为了避免与C98中的auto发生混淆C11只保留了auto作为类型指示符的用法 4️⃣auto在实际中最常见的优势用法就是跟以后会讲到的C11提供的新式for循环还有lambda表达式等进行配合使用 4、auto使用的注意事项 (1) 使用auto定义变量时必须对其进行初始化在编译阶段编译器需要根据初始化表达式来推导auto的实际类型 不初始化是不可以的哦 (2)auto并非是一种“类型”的声明而是一个类型声明时的“占位符”编译器在编译期会将auto替换为变量实际的类型 可以理解为我定义初始化一个变量 a 10; 但是int跑了于是我auto先帮你占个为位子等编译器要处理到的时候我auto再和被编译器找回来的int换回来 二、基于范围的for循环C11
在C98中如果要遍历一个数组可以按照以下方式进行
int main()
{int array[] { 1, 2, 3, 4, 5 };for (int i 0; i sizeof(array) / sizeof(array[0]); i){array[i] * 2;}for (int i 0; i sizeof(array) / sizeof(array[0]); i){cout array[i] ;}cout endl;return 0;
}这是我们熟悉的for循环写法
1、范围for的语法 对于一个有范围的集合而言由程序员来说明循环的范围是多余的有时候还会容易犯错误。因此C11中引入了基于范围的for循环。for循环后的括号由冒号“ ”分为两部分第一部分是范围内用于迭代的变量第二部分则表示被迭代的范围 请看下面代码演示
int main()
{int array[] { 1,2,3,4,5 };for (auto x : array) //依次取数组中的数据赋值给x { //自动判断结束x * 2; //自动迭代}for (auto x : array){cout x ;}cout endl;return 0;
}注意与普通循环类似可以用continue来结束本次循环也可以用break来跳出整个循环 2、范围for的使用条件
1️⃣for循环迭代的范围必须是确定的 对于数组而言就是数组中第一个元素和最后一个元素的范围对于类而言应该提供begin和end的方法begin和end就是for循环迭代的范围 注意以下代码就有问题因为for的范围不确定:
void TestFor(int array[])
{for (auto e : array)cout e endl;
}2️⃣迭代的对象要实现和的操作 关于迭代器这个问题以后会讲现在提一下没办法讲清楚现在大家了解一下就可以了 三、指针空值nullptrC11 在良好的C/C编程习惯中声明一个变量时最好给该变量一个合适的初始值否则可能会出现不可预料的错误比如未初始化的指针。如果一个指针没有合法的指向我们基本都是按照如下方式对其进行初始化 void TestPtr()
{
int* p1 NULL;
int* p2 0;
// ……
}NULL实际是一个宏在传统的C头文件(stddef.h)中可以看到如下代码 可以看到NULL可能被定义为字面常量0或者被定义为无类型指针void*的常量。不论采取何种定义在使用空值的指针时都不可避免的会遇到一些麻烦比如 //C的一个坑
void func(int)
{cout f(int) endl;
}
void func(int*)
{cout f(int*) endl;
}
int main()
{func(0);func(NULL);func((int*)NULL);func(nullptr);//nullptr --- (void*)类型return 0;
} 程序本意是想通过func(NULL)调用指针版本的 func(int*) 函数但是由于NULL被定义成0因此与程序的初衷相悖 在C98中字面常量0既可以是一个整型数字也可以是无类型的指针 (void*)常量但是编译器默认情况下将其看成是一个整型常量如果要将其按照指针方式来使用必须对其进行强转 (void*)0 注意 1. 在使用nullptr表示指针空值时不需要包含头文件因为nullptr是C11作为新关键字引入的 2. 在C11中sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同 3. 为了提高代码的健壮性在后续表示指针空值时建议最好使用nullptr 这期内容比较容易理解希望烙铁们能理解消化有所收获哦 总结 以上就是 【C】语法小课堂 的全部内容啦 本文章所在【C初阶】专栏感兴趣的烙铁可以订阅本专栏哦 前途很远也很暗但是不要怕不怕的人面前才有路。 小的会继续学习继续努力带来更好的作品 创作写文不易还多请各位大佬uu们多多支持哦