C inline:不同标准产生的问题
C语言中,在多个.c文件中调用其他文件中的inline函数时,使用默认(不加任何option)、-std=gnu89、-std=gnu99(严格按照C99标准)的编译选项,是否对inline进行声明,会产生不同的编译结果(gcc5.4.0)。
fun.c
#include<stdio.h>
#include"inline_func.h"
//int inline_func(int a);
int foo(void);
int main()
{
int a = foo();
a = inline_func(a);
printf("a = %d", a);
return 0;
}
foo.c
#include"inline_func.h"
int foo(void)
{
int x = 5;
x = inline_func(x);
return x;
}
inline_func.h
#ifndef INLINE_FUNC_H_INCLUDED
#define INLINE_FUNC_H_INCLUDED
// static int inline_func(int a);
inline int inline_func(int a)
{
return a + 1;
}
#endif // INLINE_FUNC_H_INCLUDED
而对inline函数的定义是否进行声明,在不同的编译条件下也会产生不同编译结果。究其原因,是各种不同C标准的编译器对inline、extern的不同解释规范。
主要有以下几种情况:
1.单个.c文件中,包含inline函数,而不声明其函数原型,使用C89标准编译正常,而使用C99及默认,则出现"undefined reference"编译错误。说明现代gcc编译器默认对inline函数需要进行声明,而普通的函数则没有该硬性要求。所以,为什么?
2.由于上一条规则的原因,若将inline函数放到.h文件中,在多个.c文件中包含此.h文件,如果在.h文件中未声明其inline函数,使用C89标准编译出现"multiple definition"错误,而使用C99及默认,则出现"undefined reference"编译错误。
而如果在其.h文件中声明其inline函数,则均出现"multiple definition"错误。
3.但是,如果声明时加上inline关键字(默认不加),C99编译结果是"undefined reference",好像是不把带inline的声明视为正确的声明,而C89编译结果则是"multiple definition",好像是将其认作正确的声明。
4.更为神奇的是,不声明而在inline函数的定义处加上extern关键字,C99编译"multiple definition",而C89编译通过!
总结来说,
对于C89编译,只要满足4.中的条件,编译就能通过;
而对于C99编译,必须进行声明,要么是带extern的声明,要么是不带inline关键字的声明(C99视为错误的声明),但是声明的结果就是出现"multiple definition",而不声明又会出现"undefined reference",测试发现在多个.c文件中,只声明一次编译通过,而这个声明放到哪个.c文件中都不合适,怎么解决?
查阅资料发现,将inline函数的定义加上static关键字,C89,C99编译均能通过。
如何避免这些问题?
1.在头文件中声明函数,在.c文件中定义函数
2.使用其他文件中的函数时,包含对应头文件
3.为了避免"multiple definition",多个.c文件使用的inline函数,定义为static inline
关于何时内联
在对以上几种情况下,对通过编译的可执行文件进行反汇编,发现inline函数在其调用处,并未内联,而是均使用了callq进行调用,这点很是奇怪,还请大家指点。
参考资料: