嵌入式软件工程师笔试面试题分类汇总——宏、inline

宏定义可以实现类似于函数的功能,但它并不是函数。宏定义中括号中的“参数”也不是真正的参数,在宏展开时对“参数”进行的是一对一的替换

预处理指令不是语句,行尾不要加分号

- 题型1

  1. 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(X,Y) ((X)>(Y)?(Y):(X))
//一般将参数加括号,避免带入后展开破坏原有结构
//考虑: least = MIN(*p++, b);会有什么副作用?
//该宏定义对MIN(*p++, b)的作用结果是:((*p++) <= (b) ? (*p++) : (b)) 
//这个表达式会产生副作用,指针p会作两次++自增操作。
  1. 已知一个数组table,用一个宏定义,求出数组的元素个数
#define NTBL (sizeof(table)/sizeof(table[0]))
//总大小/第一个元素的大小
  1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60*60*24*365)UL
//预处理器将为你计算常数表达式的值,因此不需要直接写出实际的值;
//这个表达式将使一个16位机的整型数溢出,因此要用到长整型符号L,告诉编译器这个常数是的长整型数;
//UL,表示无符号长整型。(结合实际)

- 题型2

1.若有宏定义:#define MOD(x,y) x%y则执行以下语句后的输出结果是

#define MOD(x,y) x%y
int a=13,b=94printf(″%d\n″,MOD(b,a+4))//输出7
//注:直接替换,不会有任何计算动作,所以带入后:b % a + 4——>结果为7

2.执行以下语句后的输出结果是:

#define N 3
#define Y(n) ((N+1)*n)
int main()
{
	printf("%d", 2*(N+Y(5+1)));
}
// 2*(N+Y(5+1)))——> 2*(3+((3+1)*5+1) = 48

3.求出以下计算结果:

#define product(x) ((x)*(x))
int main()
{
	int i = 3, j, k;
	j = product(i++);
	k = product(++i);
	printf("%d\n%d", j, k);
}
/*
	输出结果j = 9, k = 49; 这里涉及到i++和++i,由于i++是先赋值再++,
	所以j的值是3*3得来的,执行完j = product(i++);这条语句后,i的值
	为5;++i是先++再赋值,即k = (++i)*(++i),所以再计算k的时候,i的
	值实际上已经是7了,所以k = 7*7 = 49
*/

inline内联函数

显然,由于宏的诸多陷阱,没必要难为自己或者其他程序员,实际工程中更多的是使用inline内联函数

- 特征:

  • 相当于把内联函数中的内容写在调用内联函数处;
  • 相当于不用执行进入函数的步骤,直接执行函数体;
  • 相当于宏,但却比宏多了类型检查,真正的具有函数特性
  • 不能包含循环、递归、switch等复杂操作;
  • 在类声明中定义的函数,除了虚函数的其他函数都会自动隐式地当成内联函数;

- 编译器对inline函数的处理步骤:

  1. 将inline函数复制到inline函数调用处;
  2. 为所用inline函数中的局部变量分配内存空间;
  3. 将inline函数的输入参数和返回值映射到调用方法的局部变量空间中;
  4. 如果inline函数有多个返回点,将其转变为inline函数代码块末尾的分支

- 优点:

  • 内联函数同宏函数一样将在被调用处进行代码展开,省去了参数入栈、栈帧开辟与回收,结果返回等,从而提高程序运行效率
  • 内联函数相比宏函数来说,在代码展开时,会做安全检查或者自动类型转换(同普通函数),而宏定义则不会;
  • 在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不可以;
  • 内联函数在运行时可以调试,而宏定义不行;

- 缺点:

  • 代码膨胀。内联是以代码膨胀(复制)为代价,消除函数调用带来的开销。如果执⾏函数体内代码的时间,相⽐于函数调⽤的开销较⼤,那么效率的收获会很少。另⼀⽅⾯,每⼀处内联函数的调⽤都要复制代码,将使程序的总代码量增⼤,消耗更多的内存空间。
  • inline函数无法随着函数库升级而升级。inline函数的改变需要重新编译,不像non-inline可以直接链接。
  • 是否内联,程序员不可控。内联函数只是对编译器的建议,是否对函数内联,决定权在于编译器。

虚函数可以是内联函数,但是当虚函数表现多态性的时候不能内联。
[内联在编译阶段建议编译器内联,虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现多态性时(运行时)不能内联]

<未完,持续更新…>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值