[英]Confusion about inline declarations in C
我在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);
由于其中两个( newQueue
和isEmpty
)非常简单,我相信编译器可以用它们做很多好的优化,我决定为它们编写内联声明:
/* 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编译它时,它给了我一个错误。 一项快速研究表明,这些内联声明的官方方式与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.
如果要在头文件中定义函数,请将它们static
。 这应该足以让编译器内联它们( inline
只是一个额外的提示)。
如果在整个程序中包含多个标题,则标题中的非static
函数将导致多个定义。
我做了一些研究并获得了更多信息:
您可以使用inline
方式。 至少在C99。 您不能在queue.c
同时拥有内联和非内联定义。 您需要在#ifdef
包装内联定义或将它们移动到queue.c
不包含的头文件中。
您需要编写两次函数并使用预处理器,但它应该完全按照您的意愿工作。 当函数未内联时,它只会被发出一次。
在c99及更高版本中执行此操作的正确方法是仅在.c文件中具有内联函数的外部声明,而不是其定义。 这将强制为该函数创建独立代码,以便在由于某种原因无法进行内联时它将正确链接。 见: http : //www.greenend.org.uk/rjk/tech/inline.html
由于函数默认为extern
这就足够了:
#include "queue.h"
/* ... */
queue newQueue();
bool isEmpty(queue q);
你不应该在queue.c中声明它们
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.