[英]C warning: implicit declaration of function
是的,這個問題已經被問過很多次了,我一直在尋找和閱讀論壇以及SO帖子,但是答案都與此無關。 所以,我有這個主文件:
-sgbd_server.c-
#include "sgbd_server.h"
/**
* Open server pipe and return handle. -1 = error
*/
int open_server_pipe() {
return pipe_open(FIFO_NAME, O_RDONLY, S_CON_COLOR);
}
/**
* Close server pipe
*/
void close_server_pipe(int fd) {
pipe_close(fd, FIFO_NAME, S_CON_COLOR);
}
int main(int argc, char *argv[]) {
int pipe_fd;
pipe_fd = open_server_pipe();
if (pipe_fd == -1) {
perror("Cannot open pipe");
}
close_server_pipe(pipe_fd);
exit(EXIT_SUCCESS);
}
然后頭文件:
-sgbd_server.h-
#include "common.h"
#define FIFO_NAME "./sgbd_server_pipe"
#define BUFFER_SIZE PIPE_BUF
#define S_CON_COLOR 1 /* C_COLOR_RED */
-common.h-
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "console.h"
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
int pipe_open(char *f, int mode, int color);
void pipe_close(int pipe_fd, char *f, int color);
這兩個函數pipe_open
和pipe_close
中定義pipe.c
和基本上返回0
和void
。 最后一個文件在Make文件中單獨編譯。
我不是制作Make文件的專家,但是出於這個問題,這里是:
SERVER = sgbd_server
CLIENT = sgbd_client
CC = gcc
C_FLAGS = -Wall -I.
LINKER = gcc
L_FLAGS = -Wall -l pthread -Wall -I.
RM = rm -f
client: sgbd_client.o pipe.o console.o
@echo -n "Building client... "
@$(LINKER) $(L_FLAGS) -o $(CLIENT) sgbd_client.o pipe.o console.o
@echo "Complete!\n"
server: sgbd_server.o pipe.o console.o
@echo -n "Building server... "
@$(LINKER) $(L_FLAGS) -o $(SERVER) sgbd_server.o pipe.o console.o
@echo "Complete!\n"
sgbd_client.o: sgbd_client.c
@echo -n "Refreshing client sources... "
@$(CC) $(C_FLAGS) -c sgbd_client.c
@echo "Done!"
sgbd_server.o: sgbd_server.c common.h
@echo -n "Refreshing server sources..."
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
@echo "Done!"
pipe.o: pipe.c
@echo -n "Refreshing pipe sources..."
@$(CC) $(C_FLAGS) -c pipe.c
@echo "Done!"
console.o: console.c
@echo -n "Refreshing console sources..."
@$(CC) $(C_FLAGS) -c console.c
@echo "Done!"
clean:
@echo -n "Cleaning up executables and object files... "
@$(RM) $(SERVER) $(CLIENT) *.o
@echo "Ok\n"
** 注意 **:文件console.c
並實現了一些功能來控制控制台上的I / O,沒有什么花哨的地方。 如您所見,它也是單獨編譯的。
現在,當我輸入make client
,一切都很好,鳥正在簽名等。但是當我輸入make server
,它會吐出
sgbd_server.c: In function ‘open_server_pipe’:
sgbd_server.c:7: warning: implicit declaration of function ‘pipe_open’
sgbd_server.c: In function ‘close_server_pipe’:
sgbd_server.c:14: warning: implicit declaration of function ‘pipe_close’
如果有任何區別,我正在Linux amd64上運行GCC(我對此表示懷疑)。
現在,為什么要警告我呢? 這兩個函數在common.h
中聲明,該文件包含在sgbd_server.h
……我在這里缺少什么?
感謝您的時間!
** 更新 **
謝謝大家的建議。 我確實嘗試查找是否在我的包含路徑中的其他地方會包含文件common.h
而該文件會以某種方式被包含...雖然我未能找到在編譯過程中會common.h
任何文件,而不是本地common.h
( sig )我在我的源文件夾中找到了一些.ghc
文件。 由於它們不會被make clean
,因此我手動刪除了這些文件。 你猜怎么了? 沒有警告。 這些文件是什么?為什么創建它們?
首先,我認為在makefile common.h
給編譯器不是一個好主意:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
這樣會更好:
@$(CC) $(C_FLAGS) -c sgbd_server.c
頭文件通常只包含#include
。 您似乎在告訴編譯器嘗試將common.h
編譯為獨立的C文件。 這是客戶端和服務器編譯命令之間的區別,您應該對其進行修復。
我只能建議的另一件事是,您可能沒有得到您認為正在獲取的頭文件。 首先開始:
#error Urk! in common.h
在您common.h
的頂部,並確保構建在那里失敗。
如果不是,則該文件來自其他地方。 您可能還希望對sgbd_server.h
文件執行相同的操作。
根據您的編輯:
我在源文件夾中找到了一些.ghc文件。 由於不能通過make clean清除它們,因此我手動刪除了這些文件。 你猜怎么了? 沒有警告。 這些文件是什么?為什么創建它們?
這些是假設ghc
是一個錯字,而您的意思是gch
,它是gcc
生成的預編譯頭文件,至少部分地是為了加快編譯過程。 無需在構建過程中多次處理頭文件(每個包含頭文件的源文件一次),而是將其預編譯一次並使用預編譯的版本效率要高得多。
我認為這很可能是由於您在執行服務器時在編譯器命令行中包含common.h
。 默認情況下,直接提供給gcc
頭文件將被轉換為預編譯的頭文件,並在此之后優先使用。 為了測試這一點,我創建了一個qq.h
文件並執行gcc qq.h
並彈出qq.h.gch
。
考慮到刪除它們可以解決您的問題,很有可能這些文件以某種方式引起了您的問題(因為存在比真實頭文件更早的預編譯頭文件或完全其他的頭文件)。 您的編譯行很有可能:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
首先將編譯服務器程序,包括舊的預編譯頭, 然后從較新的頭文件中制作一個新的預編譯頭。
這可能就是為什么對common.h
進行更改沒有(立即)影響的原因。 你必須make ; touch common.h ; make
make ; touch common.h ; make
make ; touch common.h ; make
以確保新的預編譯頭文件在服務器程序中使用。
是否要追溯到根本原因並得到正確的解釋是一個品味問題-有一種流派,有時您應該只記錄如何解決它,而不要過分擔心,以免您陷入困境。現實本身的本質。
當然不是我,我是人格類型,它將嘗試將我的問題追溯到引起它的單個亞原子粒子上,但是有時實用主義要求我放手:-)
觀察結果:您在#define中有一個=,我懷疑您不是要在那里
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
應該是
#define CLIENT_FIFO_PREFIX "./sgbd_client_"
注釋:當原型包含正式的參數名稱(除了強制類型之外)並且函數的定義使用不同的正式參數名稱時,我偶爾會看到編譯器的奇怪行為。 即。 在您的pipe.c中。pipe.c是否包含common.h?
同樣,有條件的警衛#ifndef標頭文件名 #define標頭文件名 #endif是一個好習慣,但這與您的問題沒有直接關系。
.PMCD。
我懷疑您可能還有另一個名為common.h的文件,而不是您期望的文件。 我復制並粘貼了您的文件,並且沒有任何警告地對其進行了編譯。
您發布的文件中的include看起來應該可以使用。 一些想法還有什么可能是錯誤的:
common.h
或console.h
是否嘗試包含sgbd_server.h
,以便最終獲得循環包含? #ifdef
),並且可能將它們混合在某個地方,以便無意中排除其中一個文件? common.h
,而不是您想要的路徑?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.