簡體   English   中英

關於C中內聯聲明的困惑

[英]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);

由於其中兩個( 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編譯它時,它給了我一個錯誤。 一項快速研究表明,這些內聯聲明的官方方式與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這就足夠了:

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