C语言static和inline

C语言static和inline

C语言的static和inline的用法看似简单、但有很多坑,一些编程老手也会犯错误,网上也几乎很少有教程能讲清楚。下面先说结论,再进行推导:

  1. 头文件里不能单独出现static关键字,包括static变量和static函数,但可以有static inline函数的声明实现。
  2. 源文件里建议不要使用局部static变量,尽量使用全局static变量。
  3. inline不要单独使用,前面必须加上static,且声明和实现必须放在一起。

下面开始推导:

为什么头文件里不要出现static变量?

将static变量放到头文件里,想表达的含义或许是所有源文件都能使用同一个静态变量,但这是错误的理解。

static变量的作用域只限制与定义它的源文件中,其他源文件不能访问。如果头文件中有static变量,由于不同源文件中的static变量可以同名,那么在所有包含该头文件的源文件中都定义了仅自己可见的static变量,不同源文件中使用的也是仅属于自己的static变量,绝不是同一个。

这样做还会让源文件不清楚有哪些属于自己的static变量,程序逻辑十分混乱。因此正确的做法是杜绝在头文件中出现static变量,在源文件中定义仅自己可见的static变量。

为什么头文件里不要出现static函数?

如果在头文件中声明了static函数,那么所有包含它的源文件都会存在该static函数声明。如果一些源文件要使用该函数,由于static函数仅在当前源文件作用域可见,那么必须在每一个要使用该函数的源文件中都有函数实现,如果仅在一个源文件中实现,其他源文件使用则会编译错误,因为这个实现对于其他源文件是不可见的。

如果在每一个源文件都实现一次相同的函数,则会代码冗余、程序变大,不如定义成普通函数,仅有一处实现、一份执行码。如果在不同源文件有不同的实现,那么头文件中的函数声明就有多个不同实现,含义不明确,会造成歧义,直接放到源文件即可。

所以,在头文件里不要出现static函数的声明。

为什么尽量不使用局部static变量?

如果有以下程序:

int func() {
    static int a = 1;
    a++;
    return a;
}

多次调用该函数,返回值是不一样的,因为变量a是局部静态变量,在第一次声明定义时被初始化成1,然后生命周期就会一直存在,第二次使用该变量时,不会被赋值成1,而是保留原有的值加1再返回。这样写的含义是仅在该函数中可以使用这个static变量a,而在该源文件中的其他函数中,该变量是不可见的。但这也很容易被误解,程序逻辑不够清晰,建议定义成全局变量:

static int a = 1;
int func() {
    a++;
    return a;
}

表达相同的程序逻辑含义,唯一的区别是会放大变量a的作用域,在该文件中的所有函数都可见,但程序更加清晰明了。

为什么inline函数的声明和实现必须放在一起?

由于inline需要在调用点展开,编译器必须随处可见inline的实现,所以inline必须与函数实现放在一起才能成为内联,仅将inline放在函数声明前面不起任何作用。

为什么inline不要单独使用、必须用static inline?

关于inline关键字,不同的编译器、不同的标准、C和C++语言都有差别,非常混乱复杂。在postgresql源码中,所有inline函数都是static的。原因可能如下:对于一些编译器,在C文件中单独使用inline,可能会仅编译成普通函数,也可能会同时生成同名inline函数和普通函数的代码。对于一些C++编译器,inline可能默认都是static的。此类差异还有很多,但个人觉得没有必要完全理解这些差异以及inline的所有使用上的细节,只需要按照postgresql源码,记住这一准则即可。

为什么头文件中可以有static inline函数?

static inline的作用域仅限于当前编译单元,即源文件,允许其他编译单元有同名定义,是否内联展开取决于编译器及其优化级别。如果在不同源文件中需要使用同一个inline函数,那么可以将该函数放到公共的头文件。这只能减少代码冗余,并没有减少程序冗余,因为这样相当于每一个包含该头文件的源文件都实现了这个static函数,函数签名和实现完全相同。生成的程序中有很多份该函数的执行码,程序体积会膨胀,但内联展开节省了每次调用函数的开销,能提高程序性能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值