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

建筑招聘最好的网站自己建一个网站

建筑招聘最好的网站,自己建一个网站,商务网站建设摘要,循化网站建设公司目录 引言入门须知一、命名空间1.1 作用域限定符1.2 命名空间的意义1.3 命名空间的定义1.4 命名空间的使用 二、C输入输出2.1 cout输出2.2 cin输入2.3 std命名空间的使用惯例 三、缺省参数3.1 缺省参数概念3.2 缺省参数分类 四、函数重载4.1 函数重载概念4.2 函数重载分类… 目录 引言入门须知一、命名空间1.1 作用域限定符1.2 命名空间的意义1.3 命名空间的定义1.4 命名空间的使用 二、C输入输出2.1 cout输出2.2 cin输入2.3 std命名空间的使用惯例 三、缺省参数3.1 缺省参数概念3.2 缺省参数分类 四、函数重载4.1 函数重载概念4.2 函数重载分类4.3 C支持函数重载的原理--名字修饰(name Mangling) 五、引用5.1 引用概念5.2 引用特性5.3 使用场景5.4 传值和传引用效率对比5.5 常引用5.6 指针和引用的区别 六、内联函数6.1 内联函数概念6.2 内联函数特性6.3 C替代宏的做法 七、autoC117.1 auto简介7.2 auto的使用细则7.3 auto不能推导的场景 八、范围forC118.1 范围for的语法8.2 范围for的使用条件 九、nullptrC11总结 引言 从今天开始我们就正式的从C迈向C啦C在C的基础上解决了很多C未能解决的问题但是它的语法繁杂难学难精。所以我们也不用着急一步一个脚印系统扎实的学习C。 总之这是一个光明的起点美妙的开始程序员通向大厂的必经之路。我将怀着饱满的热情去攀登C的珠穆朗玛峰C启动 欢迎各位小伙伴关注我的专栏和我一起系统学习C共同探讨和进步哦 学习专栏 《进击的C》 入门须知 C是在C的基础之上容纳进去了面向对象编程思想并增加了许多有用的库以及编程范式等。熟悉C语言之后对C学习有一定的帮助本文目的 补充C语言语法的不足以及C是如何对C语言设计不合理的地方进行优化的比如作用域方面、IO方面、函数方面、指针方面、宏方面等。为后续类和对象学习打基础。 一、命名空间 1.1 作用域限定符 先来看看下面一段代码 根据C语言的语法局部变量优先所以打印的是2。 那么如果我想要打印全局变量怎么办呢这时C语言就办不到了C就引进了一个操作符——作用域操作符: : 作用域操作符前面代表所指向的域局部域/全局域此时前面为空代表指向全局变量 1.2 命名空间的意义 在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”: 重定义以前的定义是“函数”1.3 命名空间的定义 先来看一个情景假设一个项目分多人写代码 list.h张三写链表 struct Node {struct Node* prev;struct Node* next;int val; };queue.h李四写队列 struct Node {struct Node* next;int val; };struct Queue {struct Node* head;struct Node* tail; };test.c整合的时候就会发生Node重定义的错误 #includelist.h #includequeue.hint main() {return 0; }那么应该怎样解决呢这时就可以用到命名空间了。 定义命名空间需要使用到namespace关键字后面跟命名空间的名字然后接一对{}即可{}中即为命名空间的成员。 namespace zhangsan {struct Node{struct Node* prev;struct Node* next;int val;}; }namespace lisi {struct Node{struct Node* next;int val;};struct Queue{struct Node* head;struct Node* tail;}; }这样就完美解决了命名冲突的问题。 注意几个点 命名空间可以嵌套定义同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中一个命名空间就定义了一个新的作用域命名空间中的所有内容都局限于该命名空间中 1.4 命名空间的使用 这里有三种使用方式 指定命名空间访问加命名空间名称及作用域限定符 #includequeue.hint main() {struct lisi::Queue q;return 0; }局部展开使用using将命名空间中某个成员引入 #includequeue.h using lisi::Queue;int main() {struct Queue q;return 0; }全局展开使用using namespace 命名空间名称 引入 #includequeue.h using namespace lisi;int main() {struct Queue q;return 0; }提示 因为全局展开相当于将命名空间内部完全暴露出来多个命名空间展开后可能又会造成命名冲突。所以一般在实际的项目工程中只使用指定命名空间访问和局部展开但是平常练习中为了方便我们可以使用全局展开 二、C输入输出 2.1 cout输出 语言的开始都是问候这个新世界。 C如何实现hello world的输出呢请看下面代码 #includeiostream // std是C标准库的命名空间名C将标准库的定义实现都放到这个命名空间中 using namespace std;int main() {cout hello world endl;return 0; }使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时必须包含 iostream 头文件以及按命名空间使用方法使用std。cout和cin是全局的流对象endl是特殊的C符号表示换行输出他们都包含在包含 iostream 头文件中。是流插入运算符是流提取运算符 怎么样是不是感觉思绪一下在风中凌乱实际上cout和cin分别是ostream和istream类型的对象和也涉及运算符重载等知识这些知识我们我们后续才会学习所以我们这里只是简单学习他们的使用。 2.2 cin输入 C输入输出还有一个好处 C的输入输出可以自动识别变量类型 int main() {int arr[5];for (int i 0; i 5; i){cin arr[i];}for (int i 0; i 5; i){cout arr[i] ;//末尾打印空格}return 0; }使用C输入输出更方便不需要像printf/scanf输入输出时那样需要手动控制格式。 2.3 std命名空间的使用惯例 std是C标准库的命名空间如何展开std使用更合理呢 在日常练习中建议直接using namespace std即可这样就很方便。using namespace std展开标准库就全部暴露出来了如果我们定义跟库重名的类型/对 象/函数就存在冲突问题。该问题在日常练习中很少出现但是项目开发中代码较多、规模大就很容易出现。所以建议在项目开发中使用像std::cout这样使用时指定命名空间 using std::cout展开常用的库对象/类型等方式。 #includeiostreamint main() {std::cout hello world std::endl;return 0; }#includeiostream using std::cout; using std::endl;int main() {cout hello world endl;return 0; }三、缺省参数 3.1 缺省参数概念 缺省参数又称默认参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时如果没有指定实参则采用该形参的缺省值否则使用指定的实参。 void Fuc(int a 5) {cout a endl; }int main() {Fuc(1);//传参时使用指定实参Fuc();//没有传参时使用参数的默认值return 0; }3.2 缺省参数分类 全缺省参数 void Fuc(int a 5, int b 6, int c 7) {cout a endl;cout b endl;cout c endl; }int main() {Fuc(1, 2, 3);Fuc(1, 2);Fuc(1);Fuc();//错误写法//Fuc(,2,)//Fuc(1,,3)//……return 0; }缺省参数必须从右到左连续使用 半缺省参数 void Fuc(int a, int b 6, int c 7) {cout a endl;cout b endl;cout c endl; }//err //void Fuc(int a 5, int b, int c 7)int main() {Fuc(1, 2, 3);Fuc(1, 2);Fuc(1);return 0; }半缺省参数必须从右往左依次来给出不能间隔着给 注意 缺省参数不能在函数声明和定义中同时出现只能在声明给缺省参数 //a.hvoid Func(int a 10);// a.cppvoid Func(int a 20){}// 注意如果生命与定义位置同时出现恰巧两个位置提供的值不同那编译器就无法确定到底该用那个缺省值。缺省值必须是常量或者全局变量C语言不支持编译器不支持 四、函数重载 自然语言中一个词可以有多重含义人们可以通过上下文来判断该词真实的含义即该词被重载了。 4.1 函数重载概念 函数重载是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同常用来处理实现功能类似数据类型不同的问题。 4.2 函数重载分类 参数类型不同 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; }int main() {Add(1, 2);Add(1.1, 2.2);return 0; }参数个数不同 void f() {cout f() endl; }void f(int a) {cout f(int a) endl; }int main() {f();f(2);return 0; }参数类型顺序不同 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() {f(4, a);f(b, 9);return 0; }4.3 C支持函数重载的原理–名字修饰(name Mangling) 为什么C支持函数重载而C语言不支持函数重载呢 在C/C中一个程序要运行起来需要经历以下几个阶段预处理、编译、汇编、链接。 实际项目通常是由多个头文件和多个源文件构成而通过C语言阶段学习的编译链接我们可以知道【当前a.cpp中调用了b.cpp中定义的Add函数时】编译后链接前a.o的目标文件中没有Add的函数地址因为Add是在b.cpp中定义的所以Add的地址在b.o中。那么怎么办呢所以链接阶段就是专门处理这种问题链接器看到a.o调用Add但是没有Add的地址就会到b.o的符号表中找Add的地址然后链接到一起。那么链接时面对Add函数链接器会使用哪个名字去找呢这里每个编译器都有自己的函数名修饰规则。由于Windows下vs的修饰规则过于复杂而Linux下g的修饰规则简单易懂下面我们使用了g演示了这个修饰后的名字。通过下面我们可以看出gcc的函数修饰后名字不变。而g的函数修饰后变成【_Z函数长度函数名类型首字母】 采用C语言编译器编译后结果 结论在linux下采用gcc编译完成后函数名字的修饰没有发生改变。采用C编译器编译后结果 结论在linux下采用g编译完成后函数名字的修饰发生改变编译器将函数参数类型信息添加到修改后的名字中。 Windows下名字修饰规则 对比Linux会发现windows下vs编译器对函数名字修饰规则相对复杂难懂但道理都是类似的我们就不做细致的研究了。 通过这里就理解了C语言没办法支持重载因为同名函数没办法区分。而C是通过函数修饰规则来区分只要参数不同修饰出来的名字就不一样就支持了重载。 如果两个函数函数名和参数是一样的返回值不同是不构成重载的因为调用时编译器没办法区分。 五、引用 5.1 引用概念 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空间它和它引用的变量共用同一块内存空间。 类型 引用变量名(对象名) 引用实体 void TestRef() {int a 10;int ra a;//定义引用类型printf(%p\n, a);printf(%p\n, ra); }注意引用类型必须和引用实体是同种类型的 5.2 引用特性 引用在定义时必须初始化一个变量可以有多个引用引用一旦引用一个实体再不能引用其他实体 void TestRef() {int a 10;// int ra; // 该条语句未初始化编译时会出错int ra a;int rra a;printf(%p %p %p\n, a, ra, rra); }5.3 使用场景 做参数 void Swap(int left, int right) {int tmp left;left right;right tmp; }之前用C语言要通过形参修改实参必须传址调用用指针解引用但是在C中可以传值调用用引用来完成操作目的有时候更加简便 做返回值 如果说做参数时C语言还可以替代实现相应的功能那么做返回值时就能完成一些C语言无法替代的功能。 先来看两段代码 //代码1 int Add(int a, int b) {int c a b;return c; } //代码2 int Count() {static int n 0;n;// ...return n; }我们可以注意到 代码1创建的是临时变量开辟在栈区出作用域会销毁。而代码2创建的是静态变量开辟在静态区出作用域不会销毁。但是编译器在传值返回时总是会先将值拷贝到一个临时变量中再返回给上一层函数调用。与函数栈帧和汇编相关对于代码1是可以的但对于代码2来说无疑就是一种浪费因为静态变量出作用域并没有销毁 所以针对代码2我们可以使用传引用返回 int Count() {static int n 0;n;// ...return n; }这样就进行了优化可以直接返回变量本体而非先拷贝再返回 那我们再来看看代码1可以使用传引用返回吗 int Add(int a, int b) {int c a b;return c; }int main() {int ret Add(1, 2);Add(3, 4);cout Add(1, 2) is : ret endl;return 0; }这段代码输出结果是7是不是很意外因为创建的临时变量在出作用域时就已经将空间的使用权还给操作系统了但是通过引用我们依然可以找到变量空间本身。所以当函数再次调用时该空间的值被改成了7打印出来的自然也是7那么这就不是我们想要的效果所以不能使用传引用返回。 总结如果函数返回时出了函数作用域如果返回对象还在(还没还给系统)则可以使用引用返回如果已经还给系统了则必须使用传值返回。 5.4 传值和传引用效率对比 前面提到以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。 传参对比 #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 100000; i)TestFunc1(a);size_t end1 clock();// 以引用作为函数参数size_t begin2 clock();for (size_t i 0; i 100000; i)TestFunc2(a);size_t end2 clock();// 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl; }返回对比 #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; }通过上述代码的比较发现传值和传引用在作为传参以及返回值类型上效率相差很大。 5.5 常引用 记住一句话权限只能缩小或保持不能扩大 int main() {//权限扩大const int a 10;//int ra a;//err//权限保持const int ra a;//权限缩小int b 20;const int rb b;return 0; }注意以下写法也是可以的包含隐式类型转换此时rc不是c的别名而是转换后存储double类型临时变量的别名 int c 30;const double rc c;//隐式类型转换5.6 指针和引用的区别 在语法概念上引用就是一个别名没有独立空间和其引用实体共用同一块空间。 int main() {int a 10;int ra a;couta aendl;coutra raendl;return 0; }在底层实现上实际是有空间的因为引用是按照指针方式来实现的。 int main() {int a 10;//引用int ra a;ra 20;//指针int* pa a; *pa 20;return 0; }我们来看下引用和指针的汇编代码对比 引用和指针的不同点: 引用概念上定义一个变量的别名指针存储一个变量地址。引用在定义时必须初始化指针没有要求引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何 一个同类型实体没有NULL引用但有NULL指针在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32 位平台下占4个字节)引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小有多级指针但是没有多级引用访问实体方式不同指针需要显式解引用引用编译器自己处理引用比指针使用起来相对更安全 简单理解引用是更简便更安全的指针。但是引用并不能完全代替指针因为不能改变引用实体。所以往后在C中可能80%使用引用20%使用指针完成必须指针的功能如链表 。 六、内联函数 6.1 内联函数概念 以inline修饰的函数叫做内联函数编译时C编译器会在调用内联函数的地方展开没有函数调用建立栈帧的开销内联函数提升程序运行的效率。 请看下面代码 如果在上述函数前增加inline关键字将其改成内联函数在编译期间编译器会用函数体替换函数的调用。 查看方式 在release模式下查看编译器生成的汇编代码中是否存在call Add在debug模式下需要对编译器进行设置否则不会展开(因为debug模式下编译器默认不会对代码进行优化以下给出vs2013的设置方式) 6.2 内联函数特性 inline是一种以空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会用函数体替换函数调用缺陷可能会使目标文件变大优势少了调用开销提高程序运行效率。inline对于编译器而言只是一个建议不同编译器关于inline实现机制可能不同一般建议将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰否则编译器会忽略inline特性 下图为《Cprime》第五版关于inline的建议 inline不建议声明和定义分离分离会导致链接错误。因为inline被展开就没有函数地址了链接就会找不到。 比如下面这种写法就会报错 f.h #include iostream using namespace std;inline void f(int i);f.cpp #include F.h void f(int i) {cout i endl; }test.cpp #include F.h int main() {f(10);return 0; } // 链接错误main.obj : error LNK2019: 无法解析的外部符号 void __cdecl f(int) (?fYAXHZ)该符号在函数 _main 中被引用正确写法 将声明和定义都写在头文件中 f.h #include iostream using namespace std;inline void f(int i) {cout i endl; }6.3 C替代宏的做法 宏的优缺点 优点 增强代码的复用性。提高性能。 缺点 不方便调试宏。因为预编译阶段进行了替换导致代码可读性差可维护性差容易误用。没有类型安全的检查 。 C有哪些技术替代宏 常量定义 换用const enum短小函数定义 换用内联函数 七、autoC11 7.1 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();//auto e; //无法通过编译使用auto定义变量时必须对其进行初始化cout typeid(b).name() endl;cout typeid(c).name() endl;cout typeid(d).name() endl;return 0; }typeid().name()可以查看变量的类型名 注意 使用auto定义变量时必须对其进行初始化在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明而是一个类型声明时的“占位符”编译器在编译期会将auto替换为变量实际的类型。 上述例子好像还看不出auto的优势再来看看下面代码 #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::mapstd::string, std::string::iterator 是一个类型但是该类型太长了特别容易写错。 按以往的知识我们可以用typedef进行重定义 typedef std::mapstd::string, std::string Map; Map::iterator it m.begin();而现在我们有一种更简便的写法那就是用auto自动推导类型 auto it m.begin();7.2 auto的使用细则 auto与指针和引用结合起来使用 用auto声明指针类型时用auto和auto*没有任何区别但用auto声明引用类型时则必须加 int main() {int x 10;auto a x;auto* b x;auto c x;*a 20;*b 30;c 40;return 0; }在同一行定义多个变量 当在同一行声明多个变量时这些变量必须是相同的类型否则编译器将会报错因为编译器实际只对第一个类型进行推导然后用推导出来的类型定义其他变量。 void TestAuto() {auto a 1, b 2; auto c 3, d 4.0; // 该行代码会编译失败因为c和d的初始化表达式类型不同 }7.3 auto不能推导的场景 auto不能作为函数的参数 // 此处代码编译失败auto不能作为形参类型因为编译器无法对a的实际类型进行推导 void TestAuto(auto a) {}auto不能直接用来声明数组 void TestAuto() {int a[] {1,2,3};auto b[] {456};//err }为了避免与C98中的auto发生混淆C11只保留了auto作为类型指示符的用法auto在实际中最常见的优势用法就是跟以后会讲到的C11提供的新式for循环还有lambda表达式等进行配合使用。 八、范围forC11 8.1 范围for的语法 在C98中如果要遍历一个数组可以按照以下方式进行 void TestFor() {int arr[] { 1, 2, 3, 4, 5 };//下标for (int i 0; i sizeof(arr) / sizeof(arr[0]); i)array[i] * 2;//指针for (int* p arr; p arr sizeof(arr)/ sizeof(arr[0]); p)cout *p endl; }对于一个有范围的集合而言由程序员来说明循环的范围是多余的有时候还会容易犯错误。因此C11中引入了基于范围的for循环。for循环后的括号由冒号“ ”分为两部分第一部分是范围内用于迭代的变量第二部分则表示被迭代的范围。 范围for写法 void TestFor() {int arr[] { 1, 2, 3, 4, 5 };for(auto e : arr)e * 2;for(auto e : arr)cout e ; }简单理解自动依次取数组中数据赋值给e对象自动判断结束 这种写法是不是更加简洁所以范围for又称为语法糖因为吃起来很甜~ 8.2 范围for的使用条件 for循环迭代的范围必须是确定的 对于数组而言就是数组中第一个元素和最后一个元素的范围对于类而言应该提供begin和end的方法begin和end就是for循环迭代的范围。 那么来看看这段代码 void TestFor(int arr[]) {for(auto e : arr)cout e endl; }分析 数组传参本质传递的是指针所以数组范围是不确定的所以范围for不要用在函数内遍历数组 迭代的对象要实现和的操作 (关于迭代器这个问题以后会讲现在提一下没办法讲清楚现在大家了解一下就可以了) 九、nullptrC11 在良好的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。 所以为了修复这个早期语法设计上的bugC11引进了nullptr关键字 void f(int) {coutf(int)endl; } void f(int*) {coutf(int*)endl; } int main() {f(0);f(NULL);f(nullptr);return 0; }注意 在使用nullptr表示指针空值时不需要包含头文件因为nullptr是C11作为新关键字引入的。在C11中sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。为了提高代码的健壮性在后续表示指针空值时建议最好使用nullptr。 总结 本篇文章讲解了从C到C跨越所需的基本语法知识以及补充C语言的漏洞和背后的原理是迈向C的基础入门篇。 看到这里了还不给博主扣个 ⛳️ 点赞☀️收藏 ⭐️ 关注 ❤️ 拜托拜托这个真的很重要 你们的点赞就是博主更新最大的动力 有问题可以评论或者私信呢秒回哦。
http://www.huolong8.cn/news/300061/

相关文章:

  • 正规不收费的网站怎么做二维码直接进入网站
  • 南京公司网站开发wordpress 菜单路径
  • 发布任务注册app推广的平台佛山seo网站推广
  • 南昌互联网网站开发郑州市网站建设哪家公司好
  • 建筑网片焊网片机东营做网站seo的
  • 用discuz建设企业网站汉字logo标志设计
  • 广州市网站建设在哪里怎么一键打开wordpress
  • 网站建立快捷方式一些简约大气的网站
  • 零基础网站建设视频wordpress漫画采集
  • 青岛建站模板厂家php网站做退出的代码
  • 校园门户网站建设实施方案上海剑展投资管理有限公司
  • 怎样把有用网站做图标放在桌面福建建设工程招投标信息网
  • 免费做公司网站能在百度上搜索的到乐天seo视频教程
  • 网站建设需求单网站超级链接怎么做
  • 企业门户网站建设方案文档网络服务费会计分录
  • 做网站用域名不备案怎么弄北京土巴兔装修公司电话
  • 电子商务网站进度的基本流程免费网站软件
  • 网站上线验收南京响应式网站制作
  • 网站开发前端后端php网站建设制作流程
  • 做网站域名的成本微信网站域名
  • 网站做好了如何发布网站文章编辑器代码
  • 企业网站建设北京做兼职的网站 知乎
  • 阿里云大淘客网站建设做公司网站的总结
  • 信誉好的常州做网站玩家世界网站建设
  • 南昌高端网站制作wordpress菜单颜色
  • 专业手机网站建设公司信息流广告是什么意思
  • 东莞建站公司案例全网天下案例做网站好的网站建设公司哪家好
  • 零基础源码建设网站centos7 wordpress
  • 辽宁住房和城乡建设部网站wordpress 模板后台
  • 免费做外贸的网站平台阿里云搭建个人博客wordpress