【问题标题】:How to correctly define inline functions that handle opaque pointers?如何正确定义处理不透明指针的内联函数?
【发布时间】:2020-08-06 19:07:30
【问题描述】:

如何正确定义根据 C99 标准取消引用不透明指针的内联函数?假设我在三个文件中组织了一个程序:

opaq.h:

typedef struct Opaq Opaq;

Opaq* opaq_init(void* ptr, int size);
void opaq_free(Opaq* o);
inline int opaq_size(Opaq* o);

opaq.c:

#include <stdlib.h>
#include "opaq.h"

struct Opaq {
    void* ptr;
    int size;
};

Opaq* opaq_init(void* ptr, int size)
{
    Opaq* o = malloc(sizeof(*o));

    o->ptr = ptr;
    o->size = size;

    return o;
}

void opaq_free(Opaq* o)
{
    free(o);
}

int opaq_size(Opaq* o)
{
    return o->size;
}

ma​​in.c:

#include <stdlib.h>
#include "opaq.h"

int main(void)

{
    Opaq* o;
    int size;

    o = opaq_init(NULL, 3);
    size = opaq_size(o);
    opaq_free(o);

    return 0;
}

我希望将opaq_size 内联到main.c。据我所知,这种内联是可能的,因为内联可以在链接期间发生。但是,尝试使用 GCC 编译它会给出以下警告:

$ gcc -Winline -o main main.c opaq.c
In file included from main.c:2:0:
opaq.h:5:12: warning: inline function ‘opaq_size’ declared but never defined
 inline int opaq_size(Opaq* o);

opaq.h 中使用关键字 extern 会给出相同的警告。使用-fgnu89-inline 编译可以解决警告,但是反汇编main 会发现实际上没有发生内联。请注意,我无法在标题中定义函数(如static inline),因为结构定义超出范围。

【问题讨论】:

  • AFAIK,链接时优化内联完全独立于inline关键字请求的编译时内联,而后者固有地要求函数的代码包含在(或包含into) 正在编译的翻译单元。
  • 如果函数以任何方式取消引用该指针,则不能内联使用不透明指针的函数。如果可以,指针将不再是不透明的。

标签: c inline opaque-pointers


【解决方案1】:

据我所知,这种内联是可能的,因为内联可以在链接期间发生。

不,编译器不能内联它不知道的东西。经典链接器也无法做到这一点,因为目标文件已经编译。

不透明指针的意义在于使翻译单元独立于指针背后的类型(通常是为客户提供稳定的 ABI),因此不清楚您要完成什么。如果您以任何方式内联,包括 LTO(链接时间优化)之类的东西,它们将不再是独立的。

总之,如果您不需要它提供的保证,请不要使用不透明指针。

【讨论】:

    【解决方案2】:

    我希望 opaq_size 在 main.c 中内联。据我所知,这种内联是可能的,因为内联可以在链接期间发生。

    是和不是。在任何情况下,C 都无法要求内联。特别是,inline 关键字未指定具有该效果——它用作提示,而不是指令。但是,inline 关键字提出了与不透明类型不兼容的其他要求。具体来说,如果函数在特定翻译单元中声明为inline,则该函数的内联定义 也必须出现在 TU 中。如果所讨论的函数必须操作其类型对 TU 不透明的对象,则您无法满足该要求。

    如果您的 C 实现能够进行链接时内联,则打开启用该功能所需的任何选项。如果它提供选项或语言扩展来请求对特定函数执行此类内联,则使用它们。您想要的结果取决于特定于实现的行为,并且在您选择的特定实现中可能对您可用,也可能不可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      相关资源
      最近更新 更多