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

注册做网站的公司有哪些实用写作网站

注册做网站的公司有哪些,实用写作网站,618网络营销策划方案,太仓智能网站开发Hi~#xff01;这里是奋斗的小羊#xff0c;很荣幸您能阅读我的文章#xff0c;诚请评论指点#xff0c;欢迎欢迎 ~~ #x1f4a5;#x1f4a5;个人主页#xff1a;奋斗的小羊 #x1f4a5;#x1f4a5;所属专栏#xff1a;C语言 #x1f680;本系列文章为个人学习… Hi~这里是奋斗的小羊很荣幸您能阅读我的文章诚请评论指点欢迎欢迎 ~~ 个人主页奋斗的小羊 所属专栏C语言 本系列文章为个人学习笔记在这里撰写成文一为巩固知识二为展示我的学习过程及理解。文笔、排版拙劣望见谅。 目录 前言1、预定义符号2、#define定义常量和标识符3、#define定义宏4、带有副作用的宏参数5、宏替换的规则6、宏和函数的对比7、# 和7.1 #运算符7.2 ##运算符 8、命名的约定9、#undef10、命令行定义11、条件编译12、头文件的包含12.1 头文件被包含的方式12.1.1 本地文件包含12.1.2 库文件包含 12.2 嵌套文件的包含 总结 前言 本篇文章将详细介绍编译过程中预编译的具体细节 在C语言的学习中部分人可能会忽视这一部分的学习因为像VS这样相对强大的集成开发环境我们在写好代码后只需要开始执行即可所以部分人认为这一部分不值得我们花费时间去学习 其实不然学习C语言预编译过程可以帮助我们更深入地了解C语言的编译过程和语法特性提高代码编写的效率和质量以及拓展编程技能 1、预定义符号 C语言设置了一些预定义符号可以直接使用预定义符号也是在预编译阶段处理的 __FILE__正在编译的源文件的文件名__LINE__文件当前的行号__DATE__文件被编译的日期__TIME__文件被编译的时间__STDC__如果编译器遵循 ANSI C其值为1否则未定义 例如 2、#define定义常量和标识符 #define定义的常量和标识符在预编译阶段完成替换 基本语法 #define name stuff特别的为了区分普通常量这个name我们一般用大写形式 比如 #define MAX 10000 #define REG register#define后面的代码理论上讲只能写一行但是如果后面的代码过长我们可以使用\来实现换行相当于转义转义字符\转义了转义字符\n #define DEBUG_PRINT printf(file:%s\tline:%d\t\date:%s\ttime:%s\n,\__FILE__,__LINE__,\__DATE__,__TIME__)值得注意的是行末最好不要加;在某些场景下是没什么问题但是在大多数情况下是有语法错误的所以我们要养成良好的编程习惯行末不加; 3、#define定义宏 #define机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义宏define macro 基本语法 #define name(parament_list) stuff其中parament-list参数列表是一个由逗号隔开的符号表它们可能出现在stuff中 注意 参数列表的左括号必须与name紧邻如果两者之间有任何空白存在参数列表就会被解释为stuff的一部分 举例输入一个数输出它的平方数 #include stdio.h #define SQUARE(x) x*xint main() {int n 0;scanf(%d, n);int ret SQUARE(n);printf(%d\n, ret);return 0; }上面的代码看似没有什么问题但当我们想计算n1的平方数时就会出现问题 #include stdio.h #define SQUARE(x) x*xint main() {int n 0;scanf(%d, n);int ret SQUARE(n 1);printf(%d\n, ret);return 0; }这是为什么呢 原因就是带参数的宏在替换的时候括号内的表达式是不做任何计算的 也就是说上面替换后的形式是5 1 * 5 1为了解决这个问题我们可以在定义宏的时候给x加上括号 #define SQUARE(x) (x)*(x)这样替换后的结果就变成了(5 1)*(5 1)但是这样给单独的参数加括号的形式在某些场景下还是存在问题比如 #include stdio.h #define SQUARE(x) (x)(x)int main() {int n 0;scanf(%d, n);int ret 5 * SQUARE(n 1);printf(%d\n, ret);return 0; }那为了解决这个问题我们可以xx整体加上括号((x) (x)) #include stdio.h #define SQUARE(x) ((x)(x))int main() {int n 0;scanf(%d, n);int ret 5 * SQUARE(n 1);printf(%d\n, ret);return 0; }所以在写宏的时候一定不要吝啬括号 4、带有副作用的宏参数 当宏参数在宏的定义中出现超过一次的时候如果参数带有副作用那么你在使用这个宏的时候就可能出现危险导致不可预测的后果副作用就是表达式求值的时候出现的永久性效果 例如 x 1; //不带副作用x; //带有副作用 上面两个表达式的值是相同的但是第一个表达式x的本身没有发生改变而第二个表达式x本身发现了改变这就是副作用 例如使用宏实现求两个数的较大值 #include stdio.h #define MAX(x, y) ((x)(y)?(x):(y))int main() {int a 10;int b 20;int ret MAX(a, b);printf(%d\n, ret);return 0; }上面代码中宏参数在宏定义中出现了两次我们使用MAX(a, b);时没什么问题但当我们使用MAX(a, b);时问题就会出现 #include stdio.h #define MAX(x, y) ((x)(y)?(x):(y))int main() {int a 10;int b 20;int ret MAX(a, b);printf(%d\n, ret);printf(a %d, b %d\n, a, b);return 0; }可以发现a和b的值会发生改变就是表达式求值的时候出现了永久性效果。 与函数对比 #include stdio.hint MAX(int x, int y) {printf(a %d, b %d\n, x, y);return (x y ? x : y); }int main() {int a 10;int b 20;int ret MAX(a, b);printf(%d\n, ret);return 0; }从上面的代码中可以看出来带参数的宏替换和函数传参是非常相似的但是它们的传参是有本质区别的。 带参数的宏替换是直接将参数做整体替换替换过后的表达式是((a)(b)?(a):(b))而函数参过后的表达式是(a b ? a : b)。 5、宏替换的规则 在程序中扩展#define定义符号和宏时需要涉及几个步骤。 在调用宏时首先对参数进行检查看看是否包含任何由#define定义的符号如果有它们首先被替换替换文本随后被插入到程序中原来文本的位置对于宏参数名被他们的值所替换最后再次对结果文件进行扫描看看是否包含任何由#define定义的符号如果有重复上述步骤 例如 #include stdio.h #define M 10 #define N M 2 #define MAX(x, y) ((x)(y)?(x):(y))int main() {int ret MAX(M, N);return 0; }MAX(M, N)首先被替换成((10)(M 2)?(10):(M 2)) 然后((10)(M 2)?(10):(M 2))再被替换成((10)(10 2)?(10):(10 2)) 注意 宏参数和#define定义中可以出现其他#define定义的符号但宏不能实现递归 比如#define N M 2这个是可以的但#define N N 2是不行的。 当预处理器搜索#define定义的符号时字符串常量的内容并不被搜索 比如 #include stdio.h #define M 10 #define N M 2 #define MAX(x, y) ((x)(y)?(x):(y))int main() {printf(MAX(M, N));return 0; }可以看到宏MAX(M, N)并没有展开。 6、宏和函数的对比 宏通常被应用于执行简单的运算。 比如在两个数中找较大数用宏实现更有优势 #define MAX(x, y) ((x)(y)?(x):(y))那为什么不用函数呢原因有二 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作需要的时间更多函数调用还需要一些入栈出栈的过程所以宏比函数在程序的规模和速度方面更胜一筹。更为重要的是函数的参数必须声明为特定的类型所以函数只能在类型合适的表达式上使用。但宏可以使用于整型、长整型、浮点型等可以用于来比较的类型宏参数是无关类型的。 但是和函数相比宏还是有劣势的 每次使用宏的时候一份宏定义的代码将插入到程序中除非宏比较短否则可能大幅度增加程序的长度宏是不能调试的宏由于无关类型也就不够严禁所以宏定义是不够安全的宏可能会带来运算符优先级的问题导致程序容易出错 宏有时候能做到函数做不到的事比如宏的参数可以出现类型但是函数不行 #include stdio.h #define MALLOC(n, type) (type*)malloc(n * sizeof(type))int main() {//int* p (int*)malloc(10 * sizeof(int));int* p MALLOC(10, int);//int *p (int*)malloc(10 * sizeof(int));return 0; }宏和函数的对比: 属性#define定义宏函数代码长度每次使用时宏代码都会被插入到程序中除了非常小的宏之外程序的长度会大幅度增长函数代码只出现于一个地方每次使用这个函数时都调用那个地方的用一份代码执行速度更快存在函数的调用和返回的额外开销所以相对慢一些操作符优先级宏参数的求值是在所有周围表达式的上下文环境里除非加上括号否则邻近操作符的优先级可能会产生不可预料的结果所以建议宏在书写的时候多写括号函数参数只在函数调用的时候求值一次它的结果值传递给函数表达式的求值结果更容易预测带有副作用的参数参数可能被替换到宏体中的多个位置如果宏的参数被多次计算带有副作用的参数求值可能会产生不可预测的结果函数参数只在传参的时候求值一次结果更容易控制参数类型宏的参数与类型无关只要对参数的操作是合法的它就可以使用任何参数类型函数的参数是与类型有关的如果参数的类型不同就需要不同的函数即使他们执行的任务是不同的调试宏是不方便调试的函数是可以逐语句调试的递归宏是不能递归的函数是可以递归的 7、# 和 7.1 #运算符 #运算符将宏的一个参数转换为字符串字面量它仅允许出现在带参数的宏的替换列表中 #运算符所执行的操作可以理解为“字符串化” 比如当我们有一个变量int a 10;的时候我们想打印出the value of a is 10. 下面是常规写法 #include stdio.hint main() {int a 10;printf(the value of a is %d\n, a);return 0; }如果我们想把打印的这条代码通过宏替换来实现该怎么做呢 #include stdio.h #define PRINT(format, n) printf(the value of n is format\n, n)int main() {int a 10;PRINT(%d, a);//printf(the value of n is %d\n, a);return 0; }如果写成上面这种代码很明显并没有解决问题因为如果我们将n写成%d时并不能打印出a而只能打印出a的值那为了能打印出a本身的字面量我们就可以使用#操作符 如下 #include stdio.h #define PRINT(format, n) printf(the value of #n is format\n, n)int main() {int a 10;PRINT(%d, a);//printf(the value of a is %d\n, a);double b 3.14;PRINT(%lf, b);//printf(the value of b is %lf\n, b);return 0; }所以我们说#运算符所执行的操作可以理解为“字符串化”上面的代码中是将a和b字符串化了。 当n a的时候#n 就相当于“a” 7.2 ##运算符 ##可以把位于它两边的符号合成一个符号它允许宏定义从分离的文本片段创建标识符。##被称为记号粘合 这样的连接必须产生一个合法的标识符否则其结果就是未定义的。 比如现在有这么一个问题当我们写一个函数来求两个数的较大值的时候不同的类型我们就需要写不同的函数这样写太繁琐了我们可以使用宏来简化这件事: #include stdio.h #define GENERIC(type) \ type type##_max(type x, type y)\ {\return ((x) (y) ? (x) : (y));\ }GENERIC(int) //int int_max(int x, int y) //{ // return ((x) (y) ? (x) : (y)); //}GENERIC(double) //double double_max(double x, double y) //{ // return ((x) (y) ? (x) : (y)); //}int main() {printf(%d\n, int_max(10, 20));printf(%lf\n, double_max(3.14, 6.28));return 0; }上面的代码中我们利用宏替换来实现创建不同类型的函数type##_max中的##操作符将type和_max连接成了一个新的标识符 8、命名的约定 一般来讲函数和宏的使用语法很相似所以语言本身没法帮我们区分二者那我们平时的习惯是 把宏名全部大写函数名不要全部大写或不大写 9、#undef #undef这条指令用于移除一个宏定义 #include stdio.h #define M 10int main() {printf(%d\n, M); #undef Mprintf(%d\n, M);return 0; }如果现存的一个宏名需要被重新定义那么它的旧名字首先需要被移除 10、命令行定义 许多C编译器提供了一种能力允许在命令行中定义符号用于启动编译过程。 例如当我们根据同一个源文件想要编译出一个程序的不同版本的时候这个特性有点用处。假定某个程序中声明了一个一定长度的数组如果机器内存有限我们需要一个很小的数组但是另外一个机器内存大些我们需要一个较大的数组 编译指令 //linux 环境演示 gcc -D ARRAY_SIZE10 programe.c11、条件编译 满足条件就参与编译不满足条件就不参与编译 在编译一个程序的时候我们如果要将一条语句一组语句编译或者放弃是很方便的因为我们有条件编译指令 1. #if 常量表达式 //常量表达式由预处理器求值 //... #endif如 #define _DEBUG_ 1 int main() { #if _DEBUG_printf(a); #endifreturn 0; }2.多个分支的条件编译 #if 常量表达式 //... #elif 常量表达式 //... #else //... #endif如 #define M 1 int main() { #if M 1printf(a); #elif M 2printf(b): #elseprintf(C); #endifreturn 0; }3.判断是否被定义 //如果定义了 #if defined(symbol)或 #ifdef symbol如 #define M 2 int main() { #ifdef Mprintf(a); #endifreturn 0; }//如果没定义 #if !defined(symbol)或 #ifndef symbol4.嵌套指令 #ifdef OS_UNIX#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif #elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2():#endif #endif 条件编译通常用于跨平台性代码的编译 12、头文件的包含 12.1 头文件被包含的方式 12.1.1 本地文件包含 一般指自己创建的头文件 #include filename.h查找策略 先在源文件所在目录下查找如果该头文件未找到编译器就像查找库函数头文件一样在标准位置查找头文件如果找不到就提示编译错误。 12.1.2 库文件包含 一般指标准库中头文件的包含 #include filename.h查找策略 直接去标准路径下去查找如果找不到就提示编译错误。 那这样是不是就说明对库文件也可以使用 的形式包含呢 答案是可以的。但是这样查找的效率比较低也不容易区分是库文件还是本地文件 12.2 嵌套文件的包含 我们已经知道#include指令可以使另外一个文件被编译就像它实际出现于#include指令的地方一样。 这种替换的方式很简单预编译器先删除这条指令并用包含文件的内容替换 一个头文件被包含几次就会被实际编译几次如果重复包含对编译的压力就比较大 #include test.h #include test.h #include test.h #include test.h #include test.hint main() {return 0; }如果像上面这样写test.h文件的内容就会被拷贝5份 如果test.h文件比较大这样预处理后代码量会剧增如果工程比较大有公共使用的文件被大家都能用又不做任何的处理那么后果会不堪设想。 为了解决头文件被重复引入的问题就要用到条件编译 我们在每个头文件的开头这样写 #ifndef __FILENAME_H__ #define __FILENAME_H__//...#endif或者 #pragma once就可以避免头文件的重复引入。 总结 增强对C语言编译过程的整体理解预编译是C语言编译过程的第一阶段在预编译阶段可以对源代码进行预处理如宏定义、头文件包含等。通过学习预编译过程可以更全面地理解C语言代码的编译过程。优化代码结构预编译指令能够简化代码结构、提高代码的重用性和可维护性。学习预编译过程可以帮助程序员更好地利用预编译指令优化代码结构提高代码的质量。理解条件编译和跨平台编译条件编译是预编译指令中的重要功能可以根据不同条件编译不同的代码。通过学习预编译过程可以了解如何使用条件编译来实现跨平台编译提高代码的可移植性。
http://www.sczhlp.com/news/170851/

相关文章:

  • 做一个会Debug的程序员
  • 网站按钮特效军事国际形势最新消息
  • 购物商城网站建设方案网站后台百度统计图如何做的
  • 西宁的网站设计成全视频在线观看免费看
  • 你买域名我送网站net网站开发
  • 编程 朋友 做网站网站开发工具有组合
  • 潍坊高端网站建设如何编程做网站
  • 烟台网站建设开发网页游戏排行榜前
  • 免费企业查询网站书签制作过程
  • 网站建设大公司百度企业推广
  • 在网站的主页制作时 填写关键字苏州中设建设集团有限公司网站
  • 太原做网站费用酒泉网站建设
  • 海珠网站建设方案网站建设方法叁金手指下拉丶
  • 推荐专业的外贸建站公司江油网站制作
  • 建设设计网站公司网站自己怎么做网站啊
  • 深圳建网站制作维护南京seo新浪
  • 萍乡网站优化宛城区微网站开发
  • 晋城市建设局网站ftp工具下载网站源码教程
  • 学做网站看书会了吗重庆营销型网站建设沛宣
  • 安卓网站开发ui嘉兰图设计有限公司
  • 百度seo营销网站个人网站界面模板
  • 管庄网站建设做网站需要啥
  • 网站片区重庆百度竞价开户
  • 泰安可信赖的企业建站公司网站域名管理怎么登陆
  • 天津高端网站成都市住房和城乡建设局电话
  • 建筑行业资讯网站小程序一个页面多少钱
  • 中美网站建设差异8月4号建设部网站
  • 百度上做网站北京做网站海宇勇创
  • 淄博市沂源县建设局网站网站安全建设思考
  • 深度噪声抑制技术在语音增强中的突破