单页网站,wordpress 创建数据库,网站效果图怎么做,网站开发合同适用印花税 #x1f343; 本系列为初阶C的内容#xff0c;如果感兴趣#xff0c;欢迎订阅#x1f6a9; #x1f38a;个人主页:[小编的个人主页])小编的个人主页 #x1f380; #x1f389;欢迎大家点赞#x1f44d;收藏⭐文章 ✌️ #x1f91e; #x1… 本系列为初阶C的内容如果感兴趣欢迎订阅 个人主页:[小编的个人主页])小编的个人主页 欢迎大家点赞收藏⭐文章 ✌️ ☝️ 目录
C的发展史
命名空间
命名空间的使用
C输入输出
缺省参数
函数重载
引用 引用的使用 const引用 指针和引用的关系 C的发展史 C的起源可以追溯到1979年当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)感受到了面对项目中复杂的软件开 发任务特别是模拟和操作系统的开发工作他感受到了现有语言如C语言在表达能力、可维护性 和可扩展性方面的不足。 于是1983年Bjarne Stroustrup 在 C语言的基础上添加了面向对象编程 的特性设计出了C语言的雏形 此时的C已经有了 类、封装、继承 等核心概念为后来的⾯向对象编程奠定了基础。这⼀年该语言被 正式命名为C。 于是C的标准化工作于1989年开始在完成C标准化的第⼀个草案后不久 STL 被投票 包含到C标准中。 ⭐️ 于是C进行了一系列版本更新,如图: 值得肯定的是: C兼容C语言绝大多数的语法 所以C语言实现的程序依旧可以运行 C中需要把定义文件 代码后缀改为.cpp vs编译器看到是.cpp就会调用C编译器编译linux下要用g编译不再是gcc。 命名空间 ✨在C/C中会使用到大量变量函数类结构体等。这些变量函数类在全局变量中会引起命名冲突。而在C中引入了命名空间就是管理当前标识符的名称进行本地化以免造成命名冲突。在C中引入了namespace关键字来解决这种问题。 比如在之前可能遇到这种问题: int rand 1;
int main()
{printf(%d, rand);return 0;
} 会显示报错“rand”: 重定义以前的定义是“函数”。 这正是由于编译器在库中找到了和全局变量一样的名字造成报错。 那我们应该怎么解决这个问题呢 这需要使用namespace关键字使用规则: namespace加命名空间的名字后面跟一对花括号{}。如果我们能改变编译器的查找规则让编译器从我们定义的域中查找变量函数类等。这使namespace定义的域和全局域就相互独立起来了在不同的域中定义相同的变量函数类结构体等编译器在查找时根据命名空间的名字到对应的空间中查找就不会造成访问冲突等问题了。本质上namespace是定义出⼀个域这个域跟全局域相互独立不受影响。通过修改编译器的查找逻辑各个域互不影响。 注意: 1.命名空间域和类域不影响变量生命周期。 2.在项目文件中namespace关键字定义命名空间可以重名不过编译器认为属于同一块空间。 3.namespace只能定义在全局。支持嵌套定义。 而访问命名空间中的元素需要使用命名空间名字::。 在把C标准库都放到了一个std(standard)的命名空间中 比如: namespace li
{int rand 10;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;};
}
int main()
{printf(%d\n, li::rand);printf(%d\n, li::Add(10, 20));return 0;
} 解释: 在上述例子中 我们定义了一个li的命名空间里面分别有变量rand函数Add,结构体。我们通过li::rand来访问在li命名空间中rand变量以及函数调用。而在这里std::cout和std::endlCstd是C标准库的命名空间具体下面输入输出会讲解。 命名空间的使用 ✌️在前面的分享中我们知道命名空间本质是定义了一个本地域。编译器在查找时默认会在局部和全局变量中查找不会到命名空间中查找。所以我们需要掌握命名空间的使用的三种方式: 1.指定命名空间访问。就如刚刚上述例子,li::rand.在项目中推荐安全性好。 2.使用using将命名空间中全部成员展开。这种方式风险较大安全性不好适用于平时练习比较方便。 3.使用using将命名空间中某个成员展开。这种方式取了前两种方式的优点如果有一个不重名成员频繁使用可以考虑这种方式。 这里举例: namespace li
{int rand 10;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;};
}
//指定命名空间访问
int main()
{printf(%d\n, li::rand);printf(%d\n, li::Add(10, 20));return 0;
}
//使用using将命名空间中全部成员展开
using namespace li;
int main()
{printf(%d\n, li::rand);printf(%d\n, li::Add(10, 20));return 0;
}
//使用using将命名空间中某个成员展开
using li::Add;
int main()
{printf(%d\n, li::rand);//频繁调用Addprintf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));printf(%d\n, li::Add(10, 20));return 0;
}C输入输出 ⭐️ iostream 是 Input Output Stream 的缩写是标准的输入、输出流库定义了标准的输入、输出对象。 std::cin是 istream 类的对象主要是窄字符的标准输入流。std::cout是 ostream 类的对象主要是窄字符的标准输出流。std::endl是一个函数用于流插入输出相当于一个换行字符刷新缓存区。是流插入运算符是流提取运算符 在使用C输入输出不用指定格式。在C中输入输出都是自动识别的变量数据类型(本质上是通过函数重载实现的)、 cout,cin,endl都是在属于C标准库中的而C标准库是放在一个std的命名空间中。 在上述我们分享交代了C使用命名空间的方法。 虽然我们这里没有使用stdio.h但是依旧可以使用printf,scanf原因是iostream 间接包含了。在刚刚的例子中我们将printf都换成cout。 namespace li
{int rand 10;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;};
}
//使用using将命名空间中某个成员展开
using li::Add;
int main()
{std::cout li::rand std::endl;//频繁调用Addstd::cout Add(10,20) std::endl; std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;std::cout Add(10,20) std::endl;return 0 ;
}缺省参数 ⭐️还是由于在面向对象编程中的不方便在C中提出了缺省参数这个概念。 缺省参数是函数声明或定义时为参数指定的一个缺省值。在函数调用时如果指定了实参就使用实参否则就使用缺省值。 ⭐️缺省值分为全缺省和半缺省全缺省就是所有形参都给缺省值半缺省就是部分形参给缺省值。在给缺省值时C规定必须从右向左给缺省值不能跳跃给缺省值。 注意: 缺省值不能在函数声明和定义同时给只能在函数声明确定缺省值。 缺省值用法: using namespace std;
// 全缺省
void Func1(int a 10, int b 20, int c 30)
{cout a a endl;cout b b endl;cout c c endl endl;
}
// 半缺省
void Func2(int a, int b 10, int c 20)
{cout a a endl;cout b b endl;cout c c endl endl;
}
int main()
{Func1();Func1(1);Func1(1, 2);Func1(1, 2, 3);Func2(100);Func2(100, 200);Func2(100, 200, 300);return 0;
} 函数重载 ⭐️在C中支持了同名函数在同一作用域出现但是要求同名函数的参数不同可以是参数类型或个数如果同名函数的返回值不同不能构成重载。比如在之前我们实现计算器对于加法可能有整数整数浮点数浮点数等。现在同名函数的调用使用起来就很方便了这样的做法使得C使用起来更灵活这也反映了C的多态。
int Add(int x, int y)
{return x y;
}double Add(double x, double y)
{return x y;
}
using namespace std;
int main()
{cout Add(10, 20) endl;cout Add(10.1, 20.1) endl;return 0;
} 引用 ⭐️在我们日常生活中经常会给别人取别名比如 苏轼别称包括“东坡居士”、“苏子瞻”、“苏洵之子”等东坡居士是苏轼苏子瞻是东坡居士苏洵之子是苏子瞻他们都是苏轼。但对他的别名都是苏轼这个人没有其他人。 在C中引入了引用这个概念引用是给变量取别名并没有定义一个新变量也没有创建新的空间。 类型 引用别名 引用对象; 这里和C语言取地址操作符是一样的但是含义完全不同大家要区别开 比如: using namespace std;
int main()
{int a 10;int ra a;int rra a;int rrra a;//ra rra rrra地址完全相同cout ra endl;cout rra endl;cout rrra endl;int x 0;int b x;int c b;int d c;d;cout x endl;cout b endl;cout c endl;cout d endl;cout x b c endl;return 0;
} 这里x,b,c,d都是同一片空间。 引用的使用 首先需要注意引用一旦引用了一个实体就不能引用其他实体。可以有多个引用引用同一个变量。引用在定义时必须初始化。 例: #includeiostream
using namespace std;
int main()
{int a 10;// 编译报错“ra”: 必须初始化引⽤//int ra;int b a;int c 20;// 这并不是让b引用c因为C引用不能改变指向// 这是⼀个赋值相当于给a指向的空间赋值b c;cout a endl;cout b endl;cout c endl;cout b endl;cout c endl;cout a endl;return 0;
} 引用在使用时主要有两种用途引用传参或引用作返回值。 优点:减少拷贝提高效率和改变引用对象时同时改变被引用对象。 引用传参跟指针传参功能是类似的引用传参相对更方便⼀些。 比如在交换两个数的值在C语言需要取地址使用指针。在C中引用这方面用起来方便多了。 using namespace std;
void Swap(int rx, int ry)
{int tmp rx;rx ry;ry tmp;
}
int main()
{int x 0, y 1;cout x y endl;Swap(x, y);cout x y endl;return 0;
} 我们在之前不带头单链表创建时形参是这样的: void ListPushBack(LTNode** phead, int x) test.cpp
LTNode* plist NULL;
ListPushBack(plist,1); typedef struct ListNode
{
int val;
struct ListNode* next;
}LTNode, *PNode;
// 指针变量也可以取别名这⾥LTNode* phead就是给指针变量取别名
// 这样就不需要⽤⼆级指针了相对⽽⾔简化了程序
void ListPushBack(LTNode** phead, int x)
void ListPushBack(LTNode* phead, int x) 1.我们这里可以拆开来看,首先变量可以拿来引用那么指针也可以拿来引用。引用plist的指针形参可以用LTNode* phead来接收其中LTNode*是phead引用的类型。就像引用intb a(int为a的类型)。 2.这里用typedef简写了结构体指针*PNode,这表示指向结构体的指针等价于LTNode* 最后也可以写作:void ListPushBack(PNode phead, int x); const引用 在引用时,我们可能会触碰以下情形: 比如:int rb a*3; double d 12.34; int rd d;在这些场景下如10a*3,12.34都保存在一个临时对象(临时对象:编译器需要把一个空间暂存表达式的结果放在一个未命名的对象中)中而对于int rd d发生类型转换也是需要借助临时变量C。而C规定临时对象具有常性,不能修改所以这里就触发了权限放大必须要用常引用才可以。如果引用对象是需要放在临时变量就有常性的都需要我们使用常引用权限可以平行或缩小权限不能放大。 int main()
{//权限放大无法从“const int”转换为“int ”const int a 10;//int ra a;//正确示范:const int ra a;// 编译报错error C3892: “ra”: 不能给常量赋值//ra;// 这⾥的引用是对b访问权限的缩小int b 20;const int rb b;// 编译报错error C3892: “rb”: 不能给常量赋值//rb;//权限不能放大const int* pa a;//int* pb a;//权限可以缩小int* pc b;const int* ppc pc;return 0;
} 指针和引用的关系 在c中指针和引用的使用是紧密相关不可分割的。 语法上: 引用在定义时必须初始化指针建议初始化但不必须。 引用一旦有了实体就不可以再指向其他实体但是指针可以不断地指向其他对象。 引用可以直接访问指向对象指针需要解引用才是访问指向对象。 指针很容易出现空指针和野指针的问题引用很少出现引用使用起来相对更安全一些。 引用是一个变量的取别名不开空间指针是存储⼀个变量地址要开空间。 sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个byte64位下是8byte)。 在汇编层: 指针和引用的实现本质上是一样的。 int main()
{int a 10;int* pa a;int b 10;int d b;return 0;
} 感谢你看到这里如果觉得本篇文章对你有帮助点个赞 吧你的点赞就是我更新的最大动力。⛅️ ☀️