C 参考手册
- C 语言
- C 的历史
- 基本概念
- 表达式
- 声明
- 初始化
- 函数
- 语句
- 静态断言
- 字符常量
- 函数声明
- 函数定义
- 转义序列
- 翻译阶段
- 标识符
- 作用域
- 生存期
- 查找与命名空间
- ASCII 码表
- 类型
- 遵从性
- 算术类型
- restrict 类型限定符
- 类型
- 对象与对齐
- 主函数
- 未定义行为
- 内存模型
- if 语句
- switch 语句
- for 循环
- while 循环
- do-while 循环
- continue语句
- break 语句
- goto语句
- return 语句
- 值类别
- 求值顺序
- 整数常量
- 浮点常量
- 字符串字面量
- 复合字面量
- 常量表达式
- 隐式转换
- 成员访问运算符
- 逻辑运算符
- 比较运算符
- 算术运算符
- 赋值运算符
- 自增/自减运算符
- 其他运算符
- sizeof 运算符
- _Alignof 运算符
- 转型运算符
- C 运算符优先级
- 泛型选择
- 标量初始化
- 数组初始化
- 结构体与联合体初始化
- 指针声明
- 数组声明
- 枚举
- 存储类指定符
- const 类型限定符
- volatile 类型限定符
- 结构体声明
- 联合体声明
- 位域
- _Alignas
- typedef 声明
- 原子类型
- 外部及试探性定义
- inline 函数指定符
- _Noreturn 函数指定符
- 变长参数
- 内联汇编
- 可分析性
- 替用运算符及记号
- C 关键词
- 预处理器
- C 标准库头文件
- 类型支持
- 程序支持工具
- 变参数函数
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 算法
- 数值
- 文件输入/输出
- 本地化支持
- 原子操作库
- 线程支持库
- 实验性 C 标准库
- 有用的资源
- 符号索引
- 注释
inline 函数指定符
声明内联函数。
语法
inline function_declaration | (C99 起) | ||||||||
解释
inline
指定符的目的是提示编译器做优化,譬如函数内联,这要求编译方能见到函数的定义。编译器能(并且经常)为了优化的目的,忽略 inline
指定符的存在与否。
若编译器进行函数内联,则它会以函数体取代所有对它的调用,以避免函数调用的开销(将数据置于栈上和取得结果),这可能会生成更大的可执行文件,因为函数可能会被重复多次。结果同仿函数宏,只是用于该函数的标识符和宏指代可见于定义点的定义,而不指代调用点的定义。
不管是否进行内联,内联函数都保证下列语义:
任何拥有内部链接的函数都可以声明成 static inline
,没有其他限制。
一个非 static 的内联函数不能定义一个非 const 的函数局部 static 对象,并且不能使用文件作用域的 static 对象。
static int x; inline void f(void) { static int n = 1; // 错误:非 const 的 static 对象在非 static 的 inline 函数中 int k = x; // 错误:非 static 的 inline 函数访问 static 变量 }
若非 static 函数声明为 inline
,则必须在同一翻译单元中定义它。不使用 extern
的内联定义不会对外部可见,而且不会阻止其他翻译单元定义同一函数。这使得 inline
关键词成了 static
外另一种在头文件定义函数的方式,可以由同一程序的多个翻译单元包含该头文件。
若函数在一些翻译单元中声明为 inline
,它就不需要在处处皆声明为 inline :至多一个单元会提供常规的非 inline 非 static 函数,或是声明为 extern inline
的函数。称此翻译单元提供外部定义。若在表达式中使用拥有外部链接的函数名,则程序中必须存在一个外部定义,见一个定义规则。
若程序存在外部定义,则函数的地址始终是外部函数的地址,但当用此地址做函数调用时,调用内联函数(若存在于翻译单元中)还是外部函数是未指定的。定义于内联定义中的 static 对象与定义于外部定义中的 static 对象有别:
inline const char *saddr(void) // 用于此文件内的内联定义 { static const char name[] = "saddr"; return name; } int compare_name(void) { return saddr() == saddr(); // 未指定行为,调用可能是外部的 } extern const char *saddr(void); // 外部定义也会生成
合法的 C 程序必须不依赖于调用函数的内联版本还是外部版本。
关键词
注意
inline
关键词是从 C++ 吸收的,但在 C++ 中,若函数声明为内联,则它必须在每一个翻译单元声明为内联,而且每一个内联函数都必须有准确相同的定义( C 中,定义可以相异,只要程序行为不依赖这些差异)。另一方面, C++ 允许非 const 的函数局域 static 对象,而且所有来自一个内联函数不同定义版本的函数局部 static 对象都相同,但它们在 C 中不同。
示例
// file test.h #ifndef TEST_H_INCLUDED #define TEST_H_INCLUDED inline int sum (int a, int b) { return a+b; } #endif // 文件 sum.c #include "test.h" extern inline int sum (int a, int b); // 提供外部定义 // 文件 test1.c #include <stdio.h> #include "test.h" extern int f(void); int main(void) { printf("%d\n", sum(1, 2) + f()); } // 文件 test2.c #include "test.h" int f(void) { return sum(2, 3); }
输出:
8
引用
- C11 standard (ISO/IEC 9899:2011):
- 6.7.4 Function specifiers (p: 125-127)
- C99 standard (ISO/IEC 9899:1999):
- 6.7.4 Function specifiers (p: 112-113)