纯c中的内联函数和数据隐藏

时间:2013-12-01 17:05:33

标签: c inline visibility

假设我有以下情况

/* 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是否忽略了我的内联声明?以这种方式放置代码就像我想要在链接器级别内联函数一样,这是荒谬的。

在这种情况下通常的做法是什么?我应该牺牲安全性还是效率(跳到短程序是有点低效的)?

2 个答案:

答案 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