对 C 中的内联声明的困惑

标签 c gcc inline c99 clang

我正在用 C 语言实现队列。我的界面包含五个简单的函数来访问队列:

#ifndef QUEUE_H
#define QUEUE_H

#include <stdbool.h>
#include <stddef.h>

struct queue {
  struct cell* first;
  struct cell* last;
};

typedef struct queue queue;

extern queue newQueue(void);
extern bool  isEmpty(queue);
extern queue enqueue(queue,void*);
extern queue dequeue(queue);
extern void* front(queue);
extern void  freeQueue(queue);

由于其中两个(newQueueisEmpty)非常简单,我相信编译器可以用它们做很多好的优化,我决定为它们编写内联声明他们:

/* replacing the two lines

extern queue newQueue(void);
extern bool  isEmpty(queue);

in the original header */

extern inline queue newQueue(void) {
  queue q = { NULL, NULL };
  return q;
}

extern inline bool isEmpty(queue q) {
  return q.first == NULL;
}

用 gcc 编译很好。但是当我用 clang 编译它时,它给了我一个错误。快速研究表明,执行这些内联声明的官方方式 is different来自 GNU 风格。我可以通过 -std=gnu89 或根据上面的链接更改函数签名。我选择了第二个选项:

inline queue newQueue(void) {
  queue q = { NULL, NULL };
  return q;
}

inline bool isEmpty(queue q) {
  return q.first == NULL;
}

但是现在,当在 c99 模式下编译时,clang 和 gcc 都说了一些关于重复函数声明的问题。这是 queue.c 中的附带定义:

#include "queue.h"

/* ... */

queue newQueue() {
  queue q = { NULL, NULL };
  return q;
}

bool isEmpty(queue q) {
  return q.first == NULL;
}

我做错了什么?如何在不切换到 gnu89 模式的情况下获得我想要的东西?

这些是我用第二种风格得到的错误信息:

$ gcc -std=c99 queue.c 
queue.c:12:7: error: redefinition of ‘newQueue’
queue.h:14:21: note: previous definition of ‘newQueue’ was here
queue.c:17:6: error: redefinition of ‘isEmpty’
queue.h:19:20: note: previous definition of ‘isEmpty’ was here
$ clang -std=c99 queue.c
queue.c:12:7: error: redefinition of 'newQueue'
queue newQueue() {
      ^
In file included from queue.c:5:
./queue.h:14:21: note: previous definition is here
extern inline queue newQueue(void) {
                    ^
queue.c:17:6: error: redefinition of 'isEmpty'
bool isEmpty(queue q) {
     ^
In file included from queue.c:5:
./queue.h:19:20: note: previous definition is here
extern inline bool isEmpty(queue q) {
                   ^
2 errors generated.

最佳答案

如果您在 header 中定义函数,请将它们设为static。这应该足以让编译器将它们内联(inline 只是一个额外的提示)。

如果您在整个程序中多次包含该 header ,则 header 中的非 static 函数将导致多个定义。

我做了一些研究并获得了更多信息:

您可以那样使用内联。至少在 C99 中。您不能在 queue.c 中同时拥有内联和非内联定义。您需要将内联定义包装在 #ifdef 中或将它们移动到未包含在 queue.c 中的 header 。

您需要编写两次函数并使用预处理器,但它应该完全按照您的要求工作。当函数未被内联时,它只会被发射一次。

关于对 C 中的内联声明的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7812982/

相关文章:

c - JNI : calling C from java

从 apache 模块输出 linux 系统 whoami 的 C 代码

c++ - 在 Fedora 14 上编译 C++ 程序时出现编译错误

gcc - libavcodec.a(vc1dsp_mmx.o) : relocation R_X86_64_PC32 against symbol `ff_pw_9'

c++ - 用右值初始化左值引用

javascript - 内联样式 react 组件的可变样式对象

Kotlin 内联扩展属性

我可以在没有键盘的情况下访问标准输入吗?

c - 尝试轮询 MSP430 的键盘输入

inline - 仅用于一个文件或一个函数的 doxygen 内联源