做家政网站公司简介,湖南网上注册公司流程,东莞常平中学录取分数线2022,郑州软件开发定制鼠鼠最近在学C#xff0c;那么好#xff0c;俺来做笔记了#xff01; 目录
1.C关键字(C98)
2.命名空间
2.1.命名空间定义
2.2.命名空间的使用 3.C的输入输出
4.缺省参数
4.1缺省参数概念
4.2.缺省参数的分类
5.函数重载
5.1.函数重载概念 5.2.C支持函数…鼠鼠最近在学C那么好俺来做笔记了 目录
1.C关键字(C98)
2.命名空间
2.1.命名空间定义
2.2.命名空间的使用 3.C的输入输出
4.缺省参数
4.1缺省参数概念
4.2.缺省参数的分类
5.函数重载
5.1.函数重载概念 5.2.C支持函数重载的原理--名字修饰(name Mangling) C是在C的基础之上容纳进去了面向对象编程思想并增加了许多有用的库以及编程范式 等。本博客介绍的知识点主要是补充C语言语法的不足以及C是如何对C语言设计不合理的地方进行优化的比如作用 域方面、IO方面、函数方面、指针方面、宏方面等。
1.C关键字(C98)
C总计63个关键字C语言32个关键字。 本图片是本鼠借鉴别人的劳动成果其实本鼠的博客很多都是捏
本鼠是初学者肯定介绍不出这些个关键字的所以然来以后本鼠学习到的话会在后面的博客介绍的捏
2.命名空间
我们知道在C语言中在同一个域里面不能有重复的函数名变量名。例如C语言
#include stdio.h
#include stdlib.h
int rand 10;
// C语言没办法解决类似这样的命名冲突问题所以C提出了namespace来解决
int main()
{printf(%d\n, rand);return 0;
}
// 编译后后报错error C2365: “rand”: 重定义以前的定义是“函数”
头文件stdlib.h中定义过rand是“函数”并且“函数”rand定义在全局域当中我们又定义了全局变量rand导致rand重定义
但是在C/C中变量、函数和后面要学到的类都是大量存在的这些变量、函数和类的名称将都存 在于全局作用域中可能会导致很多冲突。所以C有了命名空间C语言可没有。使用命名空间的目的是对标识符的名称进行本地化 以避免命名冲突或名字污染。namespace关键字的出现就是针对这种问题的。
2.1.命名空间定义
定义命名空间需要使用到namespace关键字后面跟命名空间的名字然后接一对{}即可{} 中即为命名空间的成员。
注意以下代码如果写在.c文件中会报错 1.正常的命名空间定义。
// HD是命名空间的名字一般开发中是用项目名字做命名空间名
namespace HD
{// 命名空间的成员可以定义变量/函数/类型int rand 10;int Add(int left, int right){return left right;}struct LCD{int age;double weight;struct LCD* next;};
} 2. 命名空间可以嵌套。
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
} 3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。 例如本鼠有一个工程工程包含test.cpp和test.h。 在test.cpp中定义了 namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
} 在test.h中定义了 namespace HD
{typedef struct SListNode{int data; struct SListNode* next; }SListNode;char a[] {w,x,h,l,c,d};
} 那么好神奇的事发生了一个工程中的test.h和test.cpp中两个HD会被合并成一个 。 再例如本鼠有一个工程工程包含只test.cpp文件。 在test.cpp中定义了 namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}namespace HD
{typedef struct SListNode{int data; struct SListNode* next; }SListNode;char a[] {w,x,h,l,c,d};
} 那么好一个上面的两个HD也会被合并成一个 。 注意
1.一个命名空间就定义了一个新的作用域命名空间域使用using将命名空间中某个成员引入命名空间中的所有内容都局限于该命名空间中。
2.局部域和全局域会影响生命周期和访问而命名空间域只影响访问。如何影响访问请看下面本鼠介绍的编译器的访问规则。
3.命名空间封装的成员生命周期与全局变量的生命周期是一样的命名空间定义的变量都是全局变量所以说命名空间域不影响生命周期。
2.2.命名空间的使用
如何使用命名空间的成员例如
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}int main()
{//编译报错error C2065: “rand”: 未声明的标识符printf(%d, rand);return 0;
}
这里为什么报错 不得不提编译器的访问规则 1.如果没有指定域。优先访问局部域若没有访问到则访问全局域若全局域还没有访问到报错 2.如果指定了域。直接去指定的域访问若没有访问到报错 这里没有指定域所以编译器先后去局部域和全局域搜索都搜索不到rand的定义所以报错 那么如何解决有三种办法请看 1.加命名空间名称及作用域限定符::
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}
int main()
{printf(%d\n, HD::rand);printf(%d\n, HD::LCD::i);return 0;
} 作用域限定符:: 就是指定域用的。如果作用域限定符::前面为空那么默认指定访问全局域如
#includestdio.h
namespace HD
{int rand 10;
}
int rand 100;
int main()
{int rand 1000;printf(%d\n, HD::rand);printf(%d\n, ::rand);printf(%d\n, rand);return 0;
}
第一个打印10因为指定了域所以直接去命名空间域HD搜索了
第二个打印100因为指定了域所以直接去全局域搜索了
第三个打印1000因为没有指定域所以优先访问局部域且访问到了rand。 2. 使用using将命名空间中某个成员引入
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using HD::rand;
using HD::LCD::i;
int main()
{printf(%d\n, rand);printf(%d\n, i);return 0;
}这个被引入的成员能在编译器访问全局域的时候被访问到 3.使用using namespace 命名空间名称引入
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
using namespace HD::LCD;
int main()
{printf(%d\n, rand);printf(%d\n, i);return 0;
}
那么这个命名空间的全部成员都可以在编译器访问全局域的时候被访问到 本鼠顺便提一嘴这种方式慎用因为这样就将命名空间成员全部引入了那样子命名空间不就形同虚设了咩控制不好很容易导致命名冲突 介绍完了三种命名空间的使用方法本鼠考考读者老爷们下面代码运行结果是什么
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
int main()
{int rand100;printf(%d\n, rand);return 0;
}
本鼠认为结果是打印100。因为即使使用using namespace HD引入将命名空间HD的成员都引入了。但编译器对于没有指定域的话优先访问局部域那么局部域有变量rand的定义当然打印100了。 如果访问局部域没有找到rand的定义那么编译器会访问全局域。由于使用了using namespace HD引入所以编译器在访问全局域的时候能访问到命名空间HD的成员rand。
#includestdio.h
namespace HD
{int rand 10;int Add(int left, int right){return left right;}//嵌套命名空间namespace LCD{int i 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
int main()
{int RAND100;printf(%d\n, rand);return 0;
} 3.C的输入输出
本鼠写一个C版本的Hello world!来讲解
#includeiostream
// std是C标准库的命名空间名C将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{cout Hello world! endl;return 0;
} 要看懂这个代码要了解
1.std是C标准库的命名空间名C将标准库的定义实现都放到这个命名空间中。
2.cout和cin是全局的流对象endl是特殊的C符号表示换行输出他们都包含在包含 iostream 头文件中。
3.cout标准输出对象(控制台)可以笼统认为等于C语言的printfcin标准输入对象(键盘)可以笼统认为等于C语言的scanfendl可以笼统认为等于C语言的换行符\n。
4.使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时必须包含 iostream 头文件以及按命名空间使用方法使用std。
5.C中是流插入运算符是流提取运算符。当然C兼容C语言的大部分语法所以在C中也可以是左移操作符在C中也可以是右移操作符。
6.使用C输入输出更方便不需要像printf/scanf输入输出时那样需要手动控制格式。 C的输入cin输出cout可以自动识别变量类型。 那么看完上面6点看结果 其实很形象的”Hello world!“ 和endl依次顺着”流入“cout打印在控制台上咩
我们看到打印Hello world!并不用像C语言那样手动控制格式“%s”自动识别了 注意早期标准库将所有功能在全局域中实现声明在.h后缀的头文件中使用时只需包含对应 头文件即可后来将其实现在std命名空间下为了和C头文件区分也为了正确使用命名空间 规定C头文件不带.h旧编译器(vc 6.0)中还支持格式后续编译器已不支持因 此推荐使用std的方式。 std命名空间的使用惯例 std是C标准库的命名空间如何展开std使用更合理呢
1. 在日常练习中建议直接using namespace std即可这样就很方便。
2. using namespace std展开标准库就全部暴露出来了如果我们定义跟库重名的类型/对 象/函数就存在冲突问题。该问题在日常练习中很少出现但是项目开发中代码较多、规模 大就很容易出现。所以建议在项目开发中使用像std::cout这样使用时指定命名空间 using std::cout展开常用的库对象/类型等方式。 4.缺省参数
4.1缺省参数概念
缺省参数或者叫默认参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时如果没有指定实 参则采用该形参的缺省值否则使用指定的实参。
#includeiostream
using namespace std;
void Func(int a 10)
{cout a endl;
}
int main()
{Func();// 没有传参时使用参数的缺省值Func(100);// 传参时使用指定的实参return 0;
} 简单易懂好吧 缺省参数有几点注意事项
1.缺省参数不能在函数声明和定义中同时出现当函数声明和定义分离时在声明给缺省参数。
2.缺省值必须是常量或者全局变量。
3.C语言不支持编译器不支持缺省参数。
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;}
要注意半缺省参数必须从右往左依次来给出不能间隔着给 。 调用一个看看
#includeiostream
using namespace std;
void Func(int a , int b 20, int c 30)
{cout a a endl;cout b b endl;cout c c endl;
}
int main()
{Func(1,10);return 0;
}这里函数Func参数a没有指定缺省值所有调用Func函数的时候必须给a一个实参b、c随便。 5.函数重载
5.1.函数重载概念 C语言不支持同名函数但是C支持。因为C有
函数重载是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这 些同名函数的形参列表(参数个数或类型或类型顺序)不同常用来处理实现功能类似数据类型不同的问题。 1.参数类型不同构成函数重载
#includeiostream
using namespace std;
int Add(int a 10, int b 20)
{cout Add(int a10,int b20)-;return a b;
}
double Add(double a 10.0, double b 10.0)
{cout Add(double a10.0,double b10.0)-;return a b;
}
int main()
{cout Add(5, 5) endl;cout Add(10.0, 9.9) endl;return 0;
} 编译器会根据传入实参类型不同调用相应的Add函数。 2.参数个数不同构成函数重载
#includeiostream
using namespace std;
void Func(int a,int b)
{cout Func(int a,int b)endl;}
void Func(int a,int b,int c)
{cout Func(int a,int b,int c)endl;
}
int main()
{Func(1, 2);Func(1, 2, 3);return 0;
} 编译器会根据传入实参个数不同调用相应Func函数。 3.参数类型顺序不同构成函数重载
#includeiostream
using namespace std;
void Func(int a,double b)
{cout Func(int a,double b)endl;}
void Func(double a,int b)
{cout Func(double a,int b)endl;
}
int main()
{Func(1, 2.2);Func(1.1, 2);return 0;
}
编译器会根据传入实参类型顺序不同调用相应Func函数。 5.2.C支持函数重载的原理--名字修饰(name Mangling)
本鼠也说不是很清楚本鼠大概知道原理。所以本鼠大概讲讲如有不足恳请斧正
在C/C中一个程序要运行起来需要经历以下几个阶段预处理、编译、汇编、链接。
C语言编译器在链接时直接根据函数名去找函数地址。由于函数名相同导致找到多个地址编译器不知道该链接哪一个地址所以不支持函数重载。
C编译器有函数名修饰规则这个规则不统一各个编译器可能不同会引入函数参数类型信息添加到修改后的函数名中只要参数不同修饰出来的名字就不一样那么找到的地址就不同就支持函数重载了
本博客就到这里吧感谢阅读下次再见