簡體   English   中英

C警告:函數的隱式聲明

[英]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_openpipe_close中定義pipe.c和基本上返回0void 最后一個文件在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.hsig )我在我的源文件夾中找到了一些.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.hconsole.h是否嘗試包含sgbd_server.h ,以便最終獲得循環包含?
  • 您是否使用include防護(或什至其他#ifdef ),並且可能將它們混合在某個地方,以便無意中排除其中一個文件?
  • 在包含路徑的某個地方是否存在另一個common.h ,而不是您想要的路徑?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM