C99 inline


一直以来都用C++用得比较多,这个学期做操作系统的课设用回了C,结果一波內联函数居然链接不过去……查了查资料,C99引入的inline和C++的inline语义区别是很大的,我算是踩了这个坑。

C++的inline除了建议编译器把函数内容内联以外,主要的作用就是能够让你把一个函数的定义在不同的编译单元里重复,而不会报链接错误。C99的inline则不然,它的语义是:

Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.

大概可以总结为以下几点:

  1. Internal linkage的函数总可以用inline修饰,C代码中常见的static inline用法就是从这来的。
  2. 在某个编译单元中,如果某个inline函数的任意一个declaration都没有用extern修饰,那么这个编译单元中的该函数定义称为内联定义。编译器可以选择使用内联定义(即接受建议),也可以不使用该定义,此时相当于这个定义不存在(即这个函数的调用需要链接其他编译单元的符号)。
  3. 内联定义实际上是提供了对外部链接函数的一个“替代方案”。比如你在a.c中已经有了函数foo的定义,但是你在b.c中又给了个foo的内联定义,那么编译器可能会用b.c中给的内联定义,也可能视之不见。

所以C语言的inline语义的正确使用方法应该有下面三种:

static inline,不解释:

// a.h
static inline int func(int x) { /* ... */ }

这样做可以模仿C++的inline语义:

// a.h
inline int func(int x) { /* ... */ } // a.c
extern int func(int x);

提供函数的“内联版本”,由编译器进行选择:

// a.h
int func(int x); //a.c
int func(int x) { /* implementation [1] */ } // b.c
inline int func(int x) { /* implementation [2] */ }
void A(void)
{
//...
i = func(j);
//...
}

最后一种用法中,implementation [1]和implementation [2]可以是不一样的。也就是说,我们可以为已有的函数提供一个“内联版本”,这个版本不需要和原版相同。至于用哪个,则由编译器决定。

最新文章

  1. Format函数
  2. cesium+ geoserverTerrainProvide+png展示3D高程图展示
  3. 算法實例-C#-信箱排序-PigeonHoleSort
  4. [原创]自定义BaseAcitivity的实现,统一activity的UI风格样式
  5. Java server数据之(4):Redis鸟瞰
  6. 完美搞定《DOCKER IN ACTION》第二章示例
  7. codeforces magic five --快速幂模
  8. 都是类型惹的祸——小心unsigned
  9. 剑指OFFER之数组中出现次数超过一半的数字(九度OJ1370)
  10. win7下安装 WINDRIVER.TORNADO.V2.2.FOR.ARM
  11. 理解iPhone高清分辨率的问题
  12. (转)在Android的webview中定制js的alert,confirm和prompt对话框的方法
  13. Smallest Rectangle Enclosing Black Pixels 解答
  14. struts 学习之问一
  15. ServletResponse的一些知识点
  16. middleware#52
  17. Python学习-2.安装IDE
  18. SDWebImage使用,图片加载和缓存
  19. mediawiki 安装 部署 配置 使用学习
  20. thinkphp5.0读取配置

热门文章

  1. UML建模综述
  2. matlab将字符串转化为变量的方法
  3. kafka default partitioner java版本和scala版本的不同
  4. Ubuntu开放指定端口
  5. xiaopiu产品原型设计与团队实时协作平台
  6. 二、Linux用户身份
  7. Rectangle
  8. HDU 4417 【线段树+离线处理】
  9. Oracle数据库弱口令解密
  10. [AcWing303/304]任务安排2/3