假设我有以下情况
/* module a.c */
Data secret; /* data to remain hidden */
inline int veryShortProcedure( int d ) { /* using secret */ }
/* a.h */
int veryShortProcedure( int );
/* module b.c */
#include "a.h"
int procedure( int d ) {
/* something */
veryShortProcedure( d );
}
从任何C标准的角度来看,代码都是正确的,因为每当一个过程是内联的,我就不能将它拆分成原型和声明,因此我应该在a.h中定义它。
然而,代码使用-std = gnu90选项在gcc中编译。我的问题是,那它做了什么? gcc是否忽略了我的内联声明?以这种方式放置代码就像我想要在链接器级别内联函数一样,这是荒谬的。
在这种情况下通常的做法是什么?我应该牺牲安全性还是效率(跳到短程序是有点低效的)?
答案 0 :(得分:0)
你的代码是正确的C99(和C11),但它可能与你想象的不同。
看到inline
声明和非inline
一个的编译单元必须在生成的对象中发出符号。正常用法是
inline
定义(也用作声明)
文件。因此,定义在每个编译单元中都是可见的,可能由编译器(或不是)在他认为合适的任何点使用。inline
声明,用于在该编译单元中发出一次符号使用您的代码,一旦您使用了几个编译单元中的.h
,您可能会感到惊讶。链接时你会有重复的符号。
此外,您secret
的声明并非如此。您选择的表单是一个暂定的定义,可能会有相同的问题,即导致多个定义的符号。
将非inline
声明放入.c文件中,将secret
的声明加上extern
作为前缀,一切都应该如此。
答案 1 :(得分:0)
然而,代码使用-std = gnu90选项在gcc中编译。我的 问题是,那它做了什么? gcc是否忽略了我的内联 声明?
请参阅An Inline Function is As Fast As a Macro:
GCC实现了声明函数的三种不同语义 内联。
此特定于GNU C90内联:
当内联函数不是
static
时,编译器必须假定 可能有来自其他源文件的调用;自全球化的象征 在任何程序中只能定义一次,函数不能是 在其他源文件中定义,因此其中的调用不能 集成。因此,始终编译非static
内联函数 以通常的方式独立。
另请参阅Options Controlling C Dialect:-fgnu89-inline
。
这种情况下的常见做法是什么?
我认为通常的做法应该是不使用四分之一世纪前的“标准”,但至少-std=c99
。