北京建设工程信息网站,wordpress首页图片不显示,c 网站开发构想,国外网站工作室目录
函数和数据类型
函数式宏
函数和函数式宏
函数式宏和对象式宏
不带参数的函数式宏
函数式宏和逗号运算符 函数式宏和函数类似并且比函数更加灵活#xff0c;下面我们就来学习函数式宏的相关内容。
函数和数据类型
我们来编写一个程序#xff0c;它能计算出所读取…目录
函数和数据类型
函数式宏
函数和函数式宏
函数式宏和对象式宏
不带参数的函数式宏
函数式宏和逗号运算符 函数式宏和函数类似并且比函数更加灵活下面我们就来学习函数式宏的相关内容。
函数和数据类型
我们来编写一个程序它能计算出所读取数值的平方并将结果显示出来我们先来编写适用于int类型和double类型的函数。
/*整数和浮点数的平方*/
#includestdio.h/*计算int型数的平方值*/
int sqr_int(int x)
{return x * x;
}
/*计算double型数的平方值*/
double sqr_double(double x)
{return x * x;
}
int mian()
{int x;double n;printf(请输入一个整数);scanf(%d, x);printf(该整数的平方是%d\n, sqr_int(x));printf(请输入一个整数);scanf(%lf, n);printf(该整数的平方是%f\n, sqr_double(n));return 0;
}
如果我们又想计算其他数据类型的平方呢比如计算long型数的平方就得创建出一个sqr_long的函数如果接二连三的写出这种功能相近名称相似的函数程序就会充斥着这种似是而非的函数
下面我们来学习解决办法函数式宏 函数式宏
函数式宏function—like macro较之对象式宏可以进行更为复杂的代换。
#includestdio.h#define sqr(x) ((x) * (x))//计算x平方的函数式宏int main()
{int x;double n;printf(请输入一个整数);scanf(%d, x);printf(该整数的平方是%d\n, sqr(x));printf(请输入一个整数);scanf(%lf, n);printf(该整数的平方是%f\n, sqr(n));return 0;
}//#define 给出的命令如下
下文中若出现sqr☺形式的表达式就将其展开为
☺* ☺
因此在调用printf函数时就可以像下面一样展开并执行
printf(该数的平方是%d\n, ((x) * (x))); 函数和函数式宏
函数和函数式宏的调用看上去相同但也有以下几个区别 ■函数式宏sqr是在编译时展开并填入程序的因此只要能使用双目运算符 * 进行乘法运算的数据类型都能使用函数式宏。 ■而函数定义则需要每个形参都定义各自的数据类型返回值类型也都只有一种就这点而言函数较为严格。 ■函数为我们默默无闻的进行一系列的复杂处理
☞参数传递将实参复制给形参
☞函数调用和函数的返回操作函数流程的控制
☞返回值的传递
而函数式宏所做的工作只是宏展开和填入程序并不执行上述步骤。 ■根据以上特征函数式宏或许能使程序的运行速度稍微提高但是程序自身可能会变得臃肿如果宏展开式极为复杂那么在使用到它的所有地方都会填入这些复杂的表达式。 ■函数式宏在使用时必须小心比如sqra* a每次展开a的值都会递增两次。在不经意间表达式被执行了两次导致程序出现了意料之外的结果我们称这种情况为宏的副作用。 注意在定义和使用函数式宏的时候要仔细考虑是否会使用产生副作用。 ☞将函数版的sqr_int作为sqr_inta调用时a的值不会调用两次如果是宏版则要将sqra和a分开。 函数式宏和对象式宏
如果在宏名称sqr和紧邻其后的 之间插入空格进行如下宏定义
#define sqr (x) ((x) * (x)) 则sqr会被编译器当做对象式宏程序中的sqr都会被替换为(x) ((x) * (x))
因此我们在定义函数式宏时不要在宏名称和之间插入空格。 以下是计算二值之和的函数式宏
#define sum_of(x,y) x y
我们使用以下语句来调用这个函数式宏
z sum_of(a, b) * sum_of(c, d);
让我们来看看宏展开式是否符合我们的意愿呢
z a b * c d;
很显然结果不尽人意保险起见我们在宏定义时将每个参数以及整个表达式都用括号括起来
#define sum_of(x,y) ((x) (y))这样表达式就能正确展开了
z (a b) * (c d); 不带参数的函数式宏
函数式宏也可以像函数那样进行不带参数的定义例如下面这个响铃的宏alert
#define alert() (putchar(\n)) 函数式宏和逗号运算符
下面我们来介绍函数式宏的一个重要使用方法我们先来看下错误示范
#includestdio.h#define puts_alert(str) {putchar(\a); puts(str)}int main()
{int n;printf(请输入一个整数);scanf(%d, n);if(n)puts_alert(这个整数不是0);elseputs_alert(这个整数是0);return 0;
}//本程序在编译时报错因此不能运行
让我们来分析下原因
函数式宏put_alert的定义是在puts函数显示字符串str时响铃只不过这个程序在编译时出错不能运行。
main函数的if语句展开后如下图所示if语句会在第一个复合语句{ }处结束这时因为末尾的 会被视为空语句因此编译器会认为“没有if为何出现了else”即使这样也不能去掉{}否则会出现别的错误 下面就需要讲到逗号运算符了
逗号运算符 ab 按顺序判断a和b整个表达式最终生成b的判断结果
#includestdio.h#define puts_alert(str) (putchar(\a), puts(str))int main()
{int n;printf(请输入一个整数);scanf(%d, n);if(n)puts_alert(这个整数不是0);elseputs_alert(这个整数是0);return 0;
}
一般由逗号运算符连接的两个表达式“a b”在语法上可以视为一个表达式其实不仅限于逗号运算符只要是由运算符连接的多个表达式例如“a b”都可以视为一个表达式因此在本程序中if语句在语法上就是正确的。 如果宏定义中要代换两个以上的表达式则使用逗号运算符连接使其在语法上构成一个表达式。 我们对逗号运算符是怎么执行的来具体说明下
对于逗号运算符“a b”会按顺序判断表达式a和b。对左侧的a仅进行判断判断结果会被省略去对于右侧的表达式b进行判断所得到的类型和值就是逗号表达式“a b”的类型和值。
例如i1j5
运行x i j则i和j的值都会递增但是递增后j的值会被赋值给x。 感觉基本数据类型中的整型和字符型、浮点型的知识点好复杂啊