当前位置: 首页 > news >正文

网站推广建设期襄阳大型网站建设

网站推广建设期,襄阳大型网站建设,济宁百姓网免费发布信息网,二级域名网站✨✨✨学习的道路很枯燥#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一、C关键字(C98) 二、命名空间 2.1 引入 ​编辑2.2 命名空间定义 2.3 命名空间的使用 三. C输入输出 四.缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 1.全缺省参数 2… ✨✨✨学习的道路很枯燥希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一、C关键字(C98) 二、命名空间 2.1 引入 ​编辑2.2 命名空间定义 2.3 命名空间的使用 三. C输入输出 四.缺省参数 4.1 缺省参数概念 4.2 缺省参数分类  1.全缺省参数 2.半缺省参数  五. 函数重载 5.1 函数重载概念  5.2 C支持函数重载的原理--名字修饰(name Mangling) 六. 引用 6.1 引用概念 6.2 引用特性 6.3 引用权限的问题 6.4 常引用 6.5 使用场景  1. 做参数 2. 做返回值 6.6 传值、传引用效率比较  6.6.1 值和引用的作为参数类型的性能比较 6.6.2 值和引用的作为返回值类型的性能比较 6.7 引用和指针的区别 七. 内联函数  7.1 概念 7.2 特性 八. auto关键字(C11) 8.1 类型别名思考 8.2 auto简介 8.3 auto的使用细则  8.3.1. auto与指针和引用结合起来使用 8.3. 2. 在同一行定义多个变量 8.4 auto不能推导的场景 1. auto不能作为函数的参数 2. auto不能直接用来声明数组  九. 基于范围的for循环(C11 9.1 范围for的语法 9.2 范围for的使用条件  十. 指针空值nullptr(C11) 10.1 C98中的指针空值 总 前言 本篇详细介绍了C补充C语言语法的不足以及C是如何对C语言设计不合理的地方进行优化的比如作用 域方面、IO方面、函数方面、指针方面、宏方面等。 2. 为后续类和对象学习打基础。 让使用者有进一步认识而不是仅仅停留在表面更好的模拟为了更好的使用. 文章可能出现错误如有请在评论区指正让我们一起交流共同进步。 一、C关键字(C98) C总计63个关键字C语言32个关键字。 在这里我们只是简单了解一下 我们只是看一下C有多少关键字不对关键字进行具体的讲解。后面我们学到以后再细讲。 二、命名空间 2.1 引入 在C/C中变量、函数和后面要学到的类都是大量存在的这些变量、函数和类的名称将都存 在于全局作用域中可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化 以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。 #include stdio.h #include stdlib.h int rand 10; // C语言没办法解决类似这样的命名冲突问题所以C提出了namespace来解决 int main() {printf(%d\n, rand); return 0; } // 编译后后报错error C2365: “rand”: 重定义以前的定义是“函数” PS不同的作用域可以拥有同名变量  2.2 命名空间定义 定义命名空间需要使用到namespace关键字后面跟命名空间的名字然后接一对{}即可{} 中即为命名空间的成员。 1.正常的命名空间定义 namespace bit {// 命名空间中可以定义变量/函数/类型int rand 10;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;}; } 2. 命名空间可以嵌套 // test.cpp namespace N1 { int a; int b; int Add(int left, int right){return left right;} namespace N2{int c;int d;int Sub(int left, int right){return left - right;}} }3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。 // ps一个工程中的test.h和上面test.cpp中两个N1会被合并成一个 // test.h namespace N1 { int Mul(int left, int right){return left * right;} }PS一个命名空间就定义了一个新的作用域命名空间中的所有内容都局限于该命名空间中 2.3 命名空间的使用 命名空间中成员该如何使用呢 namespace bit {// 命名空间中可以定义变量/函数/类型int a 0;int b 1;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;}; } int main() {// 编译报错error C2065: “a”: 未声明的标识符printf(%d\n, a); return 0; } 前面我们提到一个命名空间就定义了一个新的作用域命名空间中的所有内容都局限于该命名空间 此时命名空间是隔离与当前局部域和全局域的也就是说我们要使用一个变量/函数时编译器的查找顺序是这样的 a.当前局部域 b.全局域   并不会从我们的设立的命名空间中查找。 那么我们就要引入一个作用域限定符  :: 命名空间的使用有三种方式 1.加命名空间名称及作用域限定符 int main() {printf(%d\n, N::a);return 0; } 2.使用using将命名空间中某个成员引入 using N::b; int main() {printf(%d\n, N::a);printf(%d\n, b);return 0; } 3.使用using namespace 命名空间名称 引入(展开命名空间) using namespce N; int main() {printf(%d\n, N::a);printf(%d\n, b);Add(10, 20);return 0; } PS:展开命名空间并不是将命名空间的代码拷贝到当前代码中而是使编译器增加能够取命名空间找到变量/函数的选择。 优先级如下 三. C输入输出 我们进入编程世界的第一个代码往往都是“hello world”C也不例外我们来写一个输出它的代码。 #includeiostream // std是C标准库的命名空间名C将标准库的定义实现都放到这个命名空间中 using namespace std; int main() { coutHello world!!!endl; return 0; }说明 1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时必须包含 iostream 头文件 以及按命名空间使用方法使用std。 2. cout和cin是全局的流对象endl是特殊的C符号表示换行输出他们都包含在包含 iostream 头文件中。 3. 是流输出运算符. 是流提取运算符。 4. 使用C输入输出更方便不需要像printf/scanf输入输出时那样需要手动控制格式。 C的输入输出可以自动识别变量类型。 5. 实际上cout和cin分别是ostream和istream类型的对象和也涉及运算符重载等知识 这些知识我们我们后续才会学习所以我们这里只是简单学习他们的使用。后面我们还有有 一个章节更深入的学习IO流用法及原理。 PS早期标准库将所有功能在全局域中实现声明在.h后缀的头文件中使用时只需包含对应 头文件即可后来将其实现在std命名空间下为了和C头文件区分也为了正确使用命名空间 规定C头文件不带.h旧编译器(vc 6.0)中还支持格式后续编译器已不支持因 此推荐使用iostreamstd的方式。   std命名空间的使用惯例 std是C标准库的命名空间如何展开std使用更合理呢 1. 在日常练习中建议直接using namespace std即可这样就很方便。 2. using namespace std展开标准库就全部暴露出来了如果我们定义跟库重名的类型/对 象/函数就存在冲突问题。该问题在日常练习中很少出现但是项目开发中代码较多、规模 大就很容易出现。所以建议在项目开发中使用像std::cout这样使用时指定命名空间 using std::cout展开常用的库对象/类型等方式。 四.缺省参数 4.1 缺省参数概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时如果没有指定实 参则采用该形参的缺省值否则使用指定的实参。 void Func(int a 0) {coutaendl; } int main() {Func(); // 没有传参时使用参数的默认值Func(10); // 传参时使用指定的实参 return 0; } 4.2 缺省参数分类  1.全缺省参数 void Func(int a 10, int b 20, int c 30){couta aendl;coutb bendl;coutc cendl;}2.半缺省参数  void Func(int a, int b 10, int c 20){couta aendl;coutb bendl;coutc cendl;}PS 1. 半缺省参数必须从右往左依次来给出不能间隔着给 2. 缺省参数不能在函数声明和定义中同时出现(若同时出现则必须保证函数声明和定义中的缺省参数必须保持一致未避免出错我们一般在声明给 //a.hvoid Func(int a 10);// a.cppvoid Func(int a 20){}// 注意如果生命与定义位置同时出现恰巧两个位置提供的值不同那编译器就无法确定到底该 用那个缺省值。3. 缺省值必须是常量或者全局变量 4. C语言不支持编译器不支持 五. 函数重载 自然语言中一个词可以有多重含义人们可以通过上下文来判断该词真实的含义即该词被重 载了。 比如以前有一个笑话国有两个体育项目大家根本不用看也不用担心。一个是乒乓球一个 是男足。前者是“谁也赢不了”后者是“谁也赢不了” 5.1 函数重载概念  函数重载是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这 些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同常用来处理实现功能类似数据类型 不同的问题。 #includeiostream using namespace std; // 1、参数类型不同 int Add(int left, int right) {cout int Add(int left, int right) endl;return left right; } double Add(double left, double right) {cout double Add(double left, double right) endl;return left right; } // 2、参数个数不同 void f() {cout f() endl; } void f(int a) {cout f(int a) endl; } // 3、参数类型顺序不同 void f(int a, char b) {cout f(int a,char b) endl; } void f(char b, int a) {cout f(char b, int a) endl; } int main() {Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, a);f(a, 10);return 0; }5.2 C支持函数重载的原理--名字修饰(name Mangling) 为什么C支持函数重载而C语言不支持函数重载呢  在C/C中一个程序要运行起来需要经历以下几个阶段预处理、编译、汇编、链接。 通过这里就理解了C语言没办法支持重载不会对函数名字进行修饰因为同名函数没办法区分。而C是通过函数修 饰规则来区分只要参数不同修饰出来的名字就不一样就支持了重载。 六. 引用 6.1 引用概念 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间它和它引用的变量共用同一块内存空间。 类型 引用变量名(对象名) 引用实体 void TestRef() {int a 10;int ra a;//定义引用类型printf(%p\n, a);printf(%p\n, ra); } 6.2 引用特性 1. 引用在定义时必须初始化 2. 一个变量可以有多个引用 3. 引用一旦引用一个实体再不能引用其他实体 void TestRef() {int a 10;// int ra; // 该条语句编译时会出错int ra a;int rra a;printf(%p %p %p\n, a, ra, rra); }6.3 引用权限的问题 引用对被引用变量的权限只能是相同或者缩小的 6.4 常引用 void TestConstRef() {const int a 10;//int ra a; // 该语句编译时会出错a为常量const int ra a;// int b 10; // 该语句编译时会出错b为常量const int b 10;double d 12.34;//int rd d; // 该语句编译时会出错类型不同const int rd d; }引用对被引用变量的权限只能是相同或者缩小的 6.5 使用场景  1. 做参数 void Swap(int left, int right) {int temp left;left right;right temp; } 2. 做返回值 int Count() {static int n 0;n;// ...return n; } 6.6 传值、传引用效率比较  以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直 接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效 率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。 6.6.1 值和引用的作为参数类型的性能比较 #include time.h struct A{ int a[10000]; }; void TestFunc1(A a){} void TestFunc2(A a){} void TestRefAndValue() {A a;// 以值作为函数参数size_t begin1 clock();for (size_t i 0; i 10000; i)TestFunc1(a);size_t end1 clock();// 以引用作为函数参数size_t begin2 clock();for (size_t i 0; i 10000; i)TestFunc2(a);size_t end2 clock(); // 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl; } 6.6.2 值和引用的作为返回值类型的性能比较 #include time.h struct A{ int a[10000]; }; A a; // 值返回 A TestFunc1() { return a;} // 引用返回 A TestFunc2(){ return a;} void TestReturnByRefOrValue() {// 以值作为函数的返回值类型size_t begin1 clock();for (size_t i 0; i 100000; i)TestFunc1();size_t end1 clock();// 以引用作为函数的返回值类型size_t begin2 clock();for (size_t i 0; i 100000; i)TestFunc2();size_t end2 clock();// 计算两个函数运算完成之后的时间cout TestFunc1 time: end1 - begin1 endl;cout TestFunc2 time: end2 - begin2 endl; } 通过上述代码的比较发现传值和指针在作为传参以及返回值类型上效率相差很大。 6.7 引用和指针的区别 在语法概念上引用就是一个别名没有独立空间和其引用实体共用同一块空间。 int main() { int a 10; int ra a; couta aendl; coutra raendl; return 0; } 在底层实现上实际是有空间的因为引用是按照指针方式来实现的。 引用和指针的不同点 1. 引用概念上定义一个变量的别名指针存储一个变量地址。 2. 引用在定义时必须初始化指针没有要求 3. 引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何 一个同类型实体 4. 没有NULL引用但有NULL指针 5. 在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32 位平台下占4个字节) 6. 引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小 7. 有多级指针但是没有多级引用 8. 访问实体方式不同指针需要显式解引用引用编译器自己处理 9. 引用比指针使用起来相对更安全 七. 内联函数  7.1 概念 以inline修饰的函数叫做内联函数编译时C编译器会在调用内联函数的地方展开没有函数调 用建立栈帧的开销内联函数提升程序运行的效率。 7.2 特性 1. inline是一种以空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会 用函数体替换函数调用缺陷可能会使目标文件变大优势少了调用开销提高程序运 行效率。 2. inline对于编译器而言只是一个建议不同编译器关于inline实现机制可能不同一般建 议将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不 是递归、且频繁调用的函数采用inline修饰否则编译器会忽略inline特性。 3. inline不建议声明和定义分离分离会导致链接错误。因为inline被展开就没有函数地址 了链接就会找不到。  八. auto关键字(C11) 8.1 类型别名思考 随着程序越来越复杂程序中用到的类型也越来越复杂经常体现在 1. 类型难于拼写 2. 含义不明确导致容易出错 #include string #include map int main() {std::mapstd::string, std::string m{ { apple, 苹果 }, { orange, 橙子 }, {pear,梨} };std::mapstd::string, std::string::iterator it m.begin();while (it ! m.end()){//....}return 0; } std::map::iterator 是一个类型但是该类型太长了特别容 易写错。聪明的同学可能已经想到可以通过typedef给类型取别名比如   #include string #include map typedef std::mapstd::string, std::string Map; int main() {Map m{ { apple, 苹果 },{ orange, 橙子 }, {pear,梨} }; Map::iterator it m.begin();while (it ! m.end()){//....}return 0; }使用typedef给类型取别名确实可以简化代码但是typedef有会遇到新的难题 typedef char* pstring; int main() {const pstring p1; // 编译成功还是失败const pstring* p2; // 编译成功还是失败return 0; }//const pstring p1; 错误的 //const pstring p1 类似于 char* const p1 const的指针必须被初始化 在编程时常常需要把表达式的值赋值给变量这就要求在声明变量的时候清楚地知道表达式的 类型。然而有时候要做到这点并非那么容易因此C11给auto赋予了新的含义。  8.2 auto简介 在早期C/C中auto的含义是使用auto修饰的变量是具有自动存储器的局部变量但遗憾的 是一直没有人去使用它大家可思考下为什么 C11中标准委员会赋予了auto全新的含义即auto不再是一个存储类型指示符而是作为一 个新的类型指示符来指示编译器auto声明的变量必须由编译器在编译时期推导而得。 int TestAuto() { return 10; } int main() { int a 10; auto b a; auto c a; auto d TestAuto(); cout typeid(b).name() endl; cout typeid(c).name() endl; cout typeid(d).name() endl; //auto e; 无法通过编译使用auto定义变量时必须对其进行初始化 return 0; }ps:使用auto定义变量时必须对其进行初始化在编译阶段编译器需要根据初始化表达式来推导auto 的实际类型。因此auto并非是一种“类型”的声明而是一个类型声明时的“占位符”编译器在编 译期会将auto替换为变量实际的类型。 8.3 auto的使用细则  8.3.1. auto与指针和引用结合起来使用 用auto声明指针类型时用auto和auto*没有任何区别但用auto声明引用类型时则必须 加 int main() {int x 10;auto a x;auto* b x;auto c x;cout typeid(a).name() endl;cout typeid(b).name() endl;cout typeid(c).name() endl;*a 20;*b 30;c 40;return 0; } 8.3. 2. 在同一行定义多个变量 当在同一行声明多个变量时这些变量必须是相同的类型否则编译器将会报错因为编译 器实际只对第一个类型进行推导然后用推导出来的类型定义其他变量。 void TestAuto() {auto a 1, b 2; auto c 3, d 4.0; // 该行代码会编译失败因为c和d的初始化表达式类型不同 } 8.4 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表达式等进行配合使用。 九. 基于范围的for循环(C11 9.1 范围for的语法 在C98中如果要遍历一个数组可以按照以下方式进行 void TestFor() { int array[] { 1, 2, 3, 4, 5 }; for (int i 0; i sizeof(array) / sizeof(array[0]); i)array[i] * 2; for (int* p array; p array sizeof(array)/ sizeof(array[0]); p)cout *p endl; } 对于一个有范围的集合而言由程序员来说明循环的范围是多余的有时候还会容易犯错误。因 此C11中引入了基于范围的for循环。for循环后的括号由冒号“ ”分为两部分第一部分是范 围内用于迭代的变量第二部分则表示被迭代的范围。  void TestFor() { int array[] { 1, 2, 3, 4, 5 }; for(auto e : array)e * 2; for(auto e : array)cout e ; return 0; } 注意与普通循环类似可以用continue来结束本次循环也可以用break来跳出整个循环。  9.2 范围for的使用条件  1. for循环迭代的范围必须是确定的 对于数组而言就是数组中第一个元素和最后一个元素的范围对于类而言应该提供 begin和end的方法begin和end就是for循环迭代的范围。 注意以下代码就有问题因为for的范围不确定 void TestFor(int array[]) {for(auto e : array)cout e endl; } 2. 迭代的对象要实现和的操作。(关于迭代器这个问题以后会讲现在提一下没办法 讲清楚现在大家了解一下就可以了)  十. 指针空值nullptr(C11) 10.1 C98中的指针空值 在良好的C/C编程习惯中声明一个变量时最好给该变量一个合适的初始值否则可能会出现 不可预料的错误比如未初始化的指针。如果一个指针没有合法的指向我们基本都是按照如下 方式对其进行初始化 void TestPtr() { int* p1 NULL; int* p2 0; // …… } NULL实际是一个宏在传统的C头文件(stddef.h)中可以看到如下代码 #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif 可以看到NULL可能被定义为字面常量0或者被定义为无类型指针(void*)的常量。不论采取何 种定义在使用空值的指针时都不可避免的会遇到一些麻烦比如 void f(int) {coutf(int)endl; } void f(int*) {coutf(int*)endl; } int main() {f(0);f(NULL);f((int*)NULL);return 0; } 程序本意是想通过f(NULL)调用指针版本的f(int*)函数但是由于NULL被定义成0因此与程序的 初衷相悖。 在C98中字面常量0既可以是一个整形数字也可以是无类型的指针(void*)常量但是编译器 默认情况下将其看成是一个整形常量如果要将其按照指针方式来使用必须对其进行强转(void *)0。  注意  1. 在使用nullptr表示指针空值时不需要包含头文件因为nullptr是C11作为新关键字引入的。 2. 在C11中sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。 3. 为了提高代码的健壮性在后续表示指针空值时建议最好使用nullptr。 总结 ✨✨✨各位读友本篇分享到内容是否更好的让你理解了数据在内存中的存储如果对你有帮助给个赞鼓励一下吧 世上没有绝望的处境只有对处境绝望的人。 感谢每一位一起走到这的伙伴我们可以一起交流进步一起加油吧。
http://www.zqtcl.cn/news/729970/

相关文章:

  • 外贸网站建设行业发展情况北京 企业网站开发
  • dedecms 倒计时 天数 网站首页创业众筹平台
  • 隆尧建设局网站wordpress彻底禁用google
  • 自己做网站需要什么技能比邻店网站开发
  • 网站建设杭州最便宜劳务公司找项目平台
  • jsp做网站毕业设计安徽省交通运输厅章义
  • 企业网站有哪几个类型广州做网站市场
  • 直播网站建设开发上海注册公司多少钱
  • 可以兼职做设计的网站备案期间能否做网站解析
  • 做发帖的网站代码seo联盟平台
  • 铁威马 Nas 做网站百度广告代运营
  • 有没有帮别人做网站小说关键词生成器
  • 那些开店的网站是自己做的吗装修平台排行榜前十名
  • 重庆智能网站建设价格毕业设计做系统跟做网站哪个容易
  • 淘宝美工做兼职的网站多多返利网站建设
  • 如何承接设计网站建设电商平台开发流程
  • 安康做网站简洁高端的wordpress个人博客
  • 酒店网站建设协议手机怎么做销售网站
  • 屏蔽网站接口js广告seminar
  • 谁有手机网站啊介绍一下wordpress 流量插件
  • 杭州网站公司google网站建设
  • 莱芜住房和城乡建设厅网站网站头部设计
  • 织梦响应式茶叶网站模板邯郸最新通告今天
  • 深圳公司网站改版通知做网站分类链接
  • 电子商务网站建设答案网络运营与维护
  • 网站登陆怎么做网站app的区别
  • 获取网站缩略图工信部2017网站备案
  • 有哪些网站可以做ps挣钱自己制作游戏
  • 旅游网站开发团队四川住房和城乡建设网站
  • 网站框架设计商城网站制作需要多少费用