ISO/IEC 9899:2011 6.7.4 函数说明符

文章详细阐述了C语言中inline函数的使用规则,包括内联函数的声明、限制和作用,以及_Noreturn函数说明符的含义,指出内联函数可以提高执行效率,但有特定的限制条件。同时,文章强调了编译单元和链接性的概念,以及如何正确使用内联和非返回函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接:https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

语法

1、function-specifier:

        inline

        _Noreturn

约束 

2  函数说明符应该只能用于函数标识符(函数名)的声明中。
3  具有外部链接的函数的内联定义,不应包含具有静态或线程存储持续时间的可修改对象的定义,也不应包含对具有内部链接的标识符的引用。

static int a = 100;

extern void hello(int b); // 创建了一个外部定义

inline void hello(int b)
{
    static int c;    // 不应该定义可修改的静态变量c
    
    c = b;

    a += b;         // 不应该引用具有内部链接的变量a
}

        内部链接(internal linkage)和外部链接 (external linkage)是和编译单元(translation unit)相关的一个术语,其主要影响函数或者对象的作用域及存储方式是全局只存储一个,还是全局有许多量的副本。
        具有external linkage的标识符可以被其它源文件使用,整个程序内有效,并且全局只有一个。

        具有internal linkage的标识符只能被本translation unit所引用,如果有多个translation unit,则会有多个副本,即每个cpp文件中都会有一个。

        在缺省情况下,常量(const)具有static属性(internal linkage),而非常量(non-const)具有external linkage 属性。

4  在一个主机端环境中,在对main函数的声明中不应该出现任何函数说明符。

语义

5  一个函数说明符可以出现多次;行为就跟只出现一次是一样的。

6  用inline函数说明符声明的一个函数是一个内联函数。将一个函数作为一个内联函数,对那个函数的调用尽可能地快。

1、内联函数在可读性方面与函数是相同的,但是在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,提高了执行效率。

2、内联函数可以调试,而宏定义是不可以调试的。内联函数与宏本质上是两个不同的概念,如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline。

3、内联函数的参数类型由编译器检查,这是对 C 的 #define 宏的一个改进。

7  任一具有内部链接的函数可以是一个内联函数。对于具有外部链接的函数,要应用以下限制:如果一个函数用一个inline函数说明符,那么它也应该被定义在同一个翻译单元。如果一个翻译单元中,一个函数的所有文件作用域内的声明包含了inline函数说明符,且没有extern,那么在那个翻译单元中的定义是一个内联定义。一个内联定义并不提供对该函数的一个外部定义,并且并不禁止在另一个翻译单元提供一个外部定义。一个内联定义提供了对一个外部定义的替代品,这样一个翻译单元可以用来在同一个翻译单元中实现对该函数的任一调用。对该函数的一次调用是否使用内联定义还是使用外部定义是未指定的。[注:由于一个内联定义区别于相应的外部定义,也区别于在其它翻译单元内的任何其他对应内联定义,因此具有静态存储持续时间的所有对应对象在每个定义中也不同。]

一个.cpp文件或者.c文件才称为一个 translation unit 编译单元,头文件(.h)不能称为一个translation unit,因为其最终会被加入到include它们的.cpp/.c文件中去,编译器编译的是.cpp/.c文件,而不是.h文件。

8  用一个_Noreturn函数说明符声明的一个函数不应该返回到其调用者

推荐的实践

9  如果用一个_Noreturn函数说明符声明的一个函数中出现了能够返回到其调用者,那么实现应该对这种情况生成一条诊断消息。

10  例1 具有外部连接的一个内联函数的声明,可以产生一个外部定义,要么是一个仅在翻译单元内可用的定义。带有extern的一个文件作用域声明创建一个外部定义。以下例子展示了一整个翻译单元。

inline double fahr(double t)
{
    return (9.0 * t) / 5.0 + 32.0;
}
inline double cels(double t)
{
    return (5.0 * (t - 32.0)) / 9.0;
}
extern double fahr(double); // 创建了一个外部定义

double convert(int is_fahr, double temp)
{
    /*  一个翻译器可以执行内联替换  */
    return is_fahr ? cels(temp) : fahr(temp);
}

11  注意,上述代码,对fahr的定义是一个外部定义,因为fahr用extern声明,但对cels的定义是内联定义。因为,cels具有外部连接且被引用,一个外部定义必须出现在另一个翻译单元中(见6.9);内联定义与外部定义是有所不同的,并且任意一个都可用于函数调用。

12  示例2

Noreturn void f () {
    abort(); // ok
}
_Noreturn void g (int i) { // causes undefined behavior if i <= 0
    if (i > 0) abort();
}
2011年12月8日,ISO正式发布了新的C语言的新标准C11,之前被称为C1X,官方名称为ISO/IEC 9899:2011。 新的标准提高了对C++的兼容性,并增加了一些新的特性。这些新特性包括: 对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符, aligned_alloc函数以及<stdalign.h>头文件。 _Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。 _Generic 关键字。 多线程(Multithreading)支持,包括:_Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。 增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>. 删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。 增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。 增加了更多浮点处理宏。 匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。 静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。 新的 fopen() 模式,(“…x”)。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。 新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。 _Atomic类型修饰符和<stdatomic.h>头文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值