wordpress建站文本教程,如何拷贝网站代码,上海知名装修公司排名榜,江岸区网站公司C推出了inline关键字#xff0c;其目的是为了替代C语言中的宏函数。
我们先来回顾宏函数#xff1a;
宏函数
现有个需求#xff1a;要求你写一个Add(x,y)的宏函数。
正确的写法有一种#xff0c;错误的写法倒是五花八门#xff0c;我们先来“见不贤而自省也。”
// …C推出了inline关键字其目的是为了替代C语言中的宏函数。
我们先来回顾宏函数
宏函数
现有个需求要求你写一个Add(x,y)的宏函数。
正确的写法有一种错误的写法倒是五花八门我们先来“见不贤而自省也。”
// 实现⼀个ADD宏函数的常⻅问题
#define ADD(int a, int b) return a b;
#define ADD(a, b) a b;
#define ADD(a, b) (a b)
分析
第一种写法宏函数不是函数它是宏在预处理阶段就替换成了目标内容。
第二种写法还是错的少括号较第一种好一点—— 在于没加分号
第三种写法还是不对不过好多了错在少括号。
正确写法
// 正确的宏实现
#define ADD(a, b) ((a) (b))
这个写对了不过“知其然亦要知其所以然”。 // 为什么不能加分号 ? // 为什么要加外⾯的括号 ? // 为什么要加⾥⾯的括号 ? //为什么不能添加分号 ;
#define Add(a,b) ((a) (b));
int main()
{int ret1 Add(1,2);//意在实现1 2并将结果赋值给ret1cout ret1 endl;//意在打印ret1return 0;
} 运行截图 好戏还在后头
cout Add(1,3) endl; 我们在前面曾说到cout 能够自动识别变量类型这里报错是因为函数的结果是它识别不了了嘛。 非也非也
宏在预处理阶段会将Add(1,3)替换成后面的表达式这里若多加了分号这行代码就在分号处中断了而作为二元操作符的 前面无操作对象 后面又有个endl;自然因为缺少参数(表达式)报错。
cout ((1) (3)); endl;//预处理阶段被替换成了如此模样
所以宏函数里分号是多余的
#define Add(a,b) ((a) (b))
int main()
{cout Add(1,3) endl;//这才能输出4return 0;
}运行截图 // 为什么要加外⾯的括号?
#define Add(a,b) (a) (b)
int main()
{cout Add(1, 3) * 2 endl;//意图输出 8 4*2return 0;
}//替换后
//cout Add(1, 3) * 2 endl;
cout (1) (3) * 2 endl;//然而据分析输出7 16 运行截图 可见外面括号是为了不改变运算表达式的结合的优先级我们写个宏函数Add本意就是为了先算加法。
// 为什么要加⾥⾯的括号?
#define Add(a,b) (a b)
int main()
{int x 1, y 2;Add(x y, x | y);//不加内括号替换成 (xy x|y)return 0;
}
//但是忽略了加法作为算数运算符的优先级其实结果会先算 yx,故而与目标结果背道而驰
得出结论宏函数不能加分号为了避免保证运算中合理的优先级应该在外面和里面加上括号。 C表示这宏函数是在预处理直接展开成了表达式不像普通函数还要建立栈帧。但是也忒麻烦了点稍有不慎结果就不正确了。
于是C引入了关键字inline 就是替代C语言中的宏函数。
inline
inline既然要替代首先它要延续宏函数的优点调用函数时不用创建栈帧直接展开还要优于宏函数方便书写—— inline 直接在函数定义的 返回类型前加上即可。
inline int Add(int x, int y)//现在写个函数inline就方便很多了
{return x y;
}
int main()
{int b Add(1,2);return 0;
} inline对于编译器⽽⾔只是⼀个建议也就是说你加了inline编译器也可以选择在调⽤的地⽅不展 开不同编译器关于inline什么情况展开各不相同因为C标准没有规定这个。inline适⽤于频繁 调⽤的短⼩函数对于递归函数代码相对多⼀些的函数加上inline也会被编译器忽略。 对于过长的函数作为内联函数若也被频繁调用此时已经不适合展开比如下面这个场景一个函数初次编译100条指令编译完后成为一条指令。在编译后的代码中直接调用一个函数尤其是在同一编译单元或模块内通常涉及很小的开销可能只是一条指令比如一个跳转。 在函数在被复用时就会执行被调用次的指令条数。 而如果编译器不阻拦这种展开直接执行10000 * 100的指令效率慢得可想而知。
所以,inline适合短小、频繁调用的函数。 inline不建议声明和定义分离到两个⽂件分离会导致链接错误。因为inline被展开就没有函数地址链接时会出现报错。 比如
//F.h 声明
#pragma once
inline void f(int a);
//F.cpp 函数定义
#include F.h
#include iostream
using namespace std;
void f(int a)
{cout a endl;
}
//执行文件
#include F.h
int main()
{f(10);return 0;
}
如上述代码所示我们把声明和定义放在两个文件
报错
内联函数编译器默认认为是不需要地址的因为已经在调用地方展开了。在测试代码中头文件展开但是只有函数F的声明找不到它的实现导致调用地方展不开函数。
为什么找不到它的实现展不开函数因为在F.cpp中虽然也包含了F.h,但是前面加了inline默认是内联函数。这时候就不会把函数的实现地址放进符号表导致测试代码中无法链接到所调用函数的定义。
等到后面有更多的知识补充我们会更好理解链接错误这一概念
总结 inline不建议声明和定义分离到两个⽂件分离会导致链接错误。