简体   繁体   English

关于C中内联声明的困惑

[英]Confusion about inline declarations in C

I am implementing an implementation of queues in C. My interface consists of five simple function to access the queue: 我在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);

Since two of them ( newQueue and isEmpty ) are so trivial that I believe that a compiler can do many good optimizations with them, I decided to write inline declarations for them: 由于其中两个( 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;
}

This compile fine with gcc. 用gcc编译好。 But when I compile it with clang, it gives me an error. 但是当我用clang编译它时,它给了我一个错误。 A quick research shows, that the official way of doing these inline declarations is different from the GNU style. 一项快速研究表明,这些内联声明的官方方式与GNU风格不同 I could either pass -std=gnu89 or change the function signatures according to the link above. 我可以传递-std=gnu89或根据上面的链接更改功能签名。 I chosed the second option: 我选择了第二个选项:

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

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

But now, both clang and gcc say something about duplicate function declarations, when compiled in c99 mode. 但是现在,当以c99模式编译时,clang和gcc都会说一些关于重复函数声明的内容。 This is the accompanying definition in queue.c : 这是queue.c的附带定义:

#include "queue.h"

/* ... */

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

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

What am I doing wrong? 我究竟做错了什么? How can I get what I want without needing to switch into gnu89 mode? 如何在不需要切换到gnu89模式的情况下获得我想要的内容?

These are the error messages I get with the second style: 这些是我用第二种风格得到的错误消息:

$ 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.

If you are defining functions in headers make them static . 如果要在头文件中定义函数,请将它们static This should be enough for compiler to inline them ( inline is just an additional hint). 这应该足以让编译器内联它们( inline只是一个额外的提示)。

Non static functions in headers will result in multiple definitions, if you include that header more than one time in your whole program. 如果在整个程序中包含多个标题,则标题中的非static函数将导致多个定义。

I have done some research and have more info: 我做了一些研究并获得了更多信息:

You can use inline that way. 您可以使用inline方式。 At least in C99. 至少在C99。 You just cannot have both inline and non-inline definitions in queue.c . 您不能在queue.c同时拥有内联和非内联定义。 You need wrap inline definitions in #ifdef or move them to header not included in queue.c . 您需要在#ifdef包装内联定义或将它们移动到queue.c不包含的头文件中。

You need to write the functions twice and play with the preprocessor, but it should work exactly as you want. 您需要编写两次函数并使用预处理器,但它应该完全按照您的意愿工作。 When function is not inlined, it will be emitted only once. 当函数未内联时,它只会被发出一次。

The proper way of doing this in c99 and onward is to merely have an external declaration of an inline function in the .c file instead of a definition of it. 在c99及更高版本中执行此操作的正确方法是仅在.c文件中具有内联函数的外部声明,而不是其定义。 This will force standalone code to be created for that function so that it will link properly if inlining is not possible for some reason. 这将强制为该函数创建独立代码,以便在由于某种原因无法进行内联时它将正确链接。 See: http://www.greenend.org.uk/rjk/tech/inline.html 见: http//www.greenend.org.uk/rjk/tech/inline.html

Since functions default to extern this is sufficient: 由于函数默认为extern这就足够了:

queue.c queue.c

#include "queue.h"

/* ... */

queue newQueue();

bool isEmpty(queue q);

你不应该在queue.c中声明它们

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM