预处理
预处理是指程序在编译之前所进行的处理。预处理命令最大的特征是以“#”开头,如#include、#define等。在C语言中的预处理主要包括三方面的内容:宏定义、文件包含以及条件编译。合理地使用预处理命令,有利于程序的阅读、调试和不同平台间的移植。
宏定义
宏,就是将一组命令组合在一起,作为一个独立的命令完成一系列任务。在C语言的源程序中允许用一个标识符来表示一个字符串,此时该标识符被称为宏名,而该字符串被称为宏体。包含宏定义的程序在编译预处理的时候,预处理程字将会对程序中所有出现宏名的地方都用宏体去代替,该过程被称为宏替换。
在C语言中,宏分为带参数和不带参数两种。
不带参数的宏定义
//#define 宏名 字符串//不带参数的宏定义 #define Max 100
其作用为用宏名Max去代替字符串100,当编写源代码时所有需要使用100的地方都可以用Max来代替,当我们对源程序编译时,先由源程序进行宏替换,即用100来置换使用宏名Max后再进行编译。
常见问题:
#define<stdio.h> #define Max 100+y int main() { int s,y; scanf("%d",&y); s=Max*2; printf("%d",s); }
*这里我们容易简单的认为替换后的Max为(100+y)2,事实上并非如此,宏定义是简单的替换真实情况应该wei(100+y2),为了预防这种误解,在我们编写程序的时候可以加上括号(100+y),我们还应注意 *
1. 宏替换只是一种简单的替换,在任何时候它都是用字符串来取代宏名,所以任何错误都是编译是被发现的,在预处理时不作任何检查。
2. 宏定义并不是语句,所有不需要在其后面加上分号,加分号不会报错,但在一些情况下也会造成不必要的错误。
3. 诺在程序之前需要解除某个宏定义的作用域,则需要所有(#undef)
#define Max 100 ... int main() { } #undef Max ... void fi() { ... }
其作用在于,Max宏只在main()函数中有效,而对于f1函数无效。
4. 诺在程序中用引号将宏名括起来则预处理程序不对其进行宏替换。如:
#define Max 100 int main() { printf("Max"); }
5. 宏定义允许嵌套使用,如后一个宏去使用前一个宏的定义。
#define Max 100 #define Math Max*2
带参数的宏定义
在C语言中,宏定义还可以带参数,在宏定义中使用的参数称为形式参数,而在宏替换后所用的参数称为实际参数,这与函教定义和调用过程中是一致的。
#define 宏名(形式参数表) 字符串 //在调用时 宏名(实际参数表)如 #define Max(x) 100*x*y k=Max(10); //在宏调用编译后,其就会变为k=100*10*10;
同样带参数的宏我们也需要注意以下问题:
1. 宏名和参数表之间不能有空格,否则会将宏名后面的字符串替换。
2. 与无参数的宏定义一样,带参数的宏更需要注意括号的使用。因为对于带参数的宏来说,其参数可以是表达式,在某些时候如果不使用括号的话会产生意想不到的后果。
#include<stdio.h> #define Math() y*y int main() { int a,b; a=3; b=Math(a+1); }
在该程序中我们不难看出,宏替换后b=Math()变为了b=a+1a+1,显然我们每天达到预期的结果诺我们在进行宏定义时加上括号,就可以有效的避免这种情况。
3. 注意带参数的宏与函数的区别,有时两者得到得结果一致,但有时两者又有很大区别*
#include<stdio.h> #define Math(y) ((y)*(y)) int Math2(int c) { return ((y)*(y)) } int main() { int a,b; a=3; b=Math(a++); //b=Math(a++) }
上面是使用宏定义和函数进行编写的例子,从形式上来看, 两者都差不多。但是对于前者来说,由于是宏定义,因此在预编译的时候发生了宏替换,即语句“b=Math(a++);"变为“b=((a++)(a++));";由于具有++操作,当执行首面的a++操作后,a实际上变为4,因此该语句实际上是进行了b=34操作。对于后者来道由于使用的是函数,只是在传参时将a+传入, 因此结果是b=33.由此可见,宏定和函数虽然在形式上相似,但其本质是不同的。*
每日一题
对正整数1234567890987654321123456789,计算其各位数字之和,⽤汉语拼⾳顺序输出和的
每⼀位数字(输出⽤逗号分隔)
输出:yi san wu
最后的话 :如果大家觉得这篇文章对你们有帮助的话希望你们能够点点关注,你们的关注是我继续写下去的动力,谢谢大家。
答案及解析
思路:1. 由n的值已经超过long long类型的范围可知只能用字符数组储存
使用字符数组储存数字也能更好地分割每一位数
2. 遍历字符数组将每个字符转换为数字进行累加
3. 由于每个数字的拼音刚好对应该数字的数组下标,故可以直接设置一个二维字符数组存储
4. 将累加值的每一位数字逆序输出即可
#include<stdio.h> int main(void){ int i,n=0,m,wxx3[101]; char wxx[10][5]= {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"}; char wxx2[101]="1234567890987654321123456789"; //wxx2[i]-'0'即可将字符转换为数字 for(i=0,m=0;wxx2[i]!='\0';i++) m+=wxx2[i]-'0'; //循环获取累加值的每一位数字 //因为每次获取的是右边的数字需要逆序输出 //故先使用数组保存起来 while(m){ wxx3[n++]=m%10; m/=10; } //将数组存储的累加值各位数逆序输出对应的字符串 for(i=n-1;i>=0;i--) printf("%s%c",wxx[wxx3[i]],i!=0?' ':'\n'); return 0; }