代码之家  ›  专栏  ›  技术社区  ›  Yanick Rochon

C警告:函数的隐式声明

  •  1
  • Yanick Rochon  · 技术社区  · 15 年前

    是的,这个问题已经被问过很多次了,我一直在寻找和阅读论坛,等等帖子,但是答案都与这个问题无关(或者看起来是这样)。所以,我有这个 主要的 文件:

    -- 服务器.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 */
    

    -- 普通.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文件中单独编译。

    我不是制作文件的专家,但为了这个问题,这里是:

    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’
    

    如果GCC有什么不同的话(我怀疑),我将在Linux amd64上运行它。

    为什么它会警告我?这两个函数在 common.h ,包括在 sgbd_server.h ... 我错过了什么?

    谢谢你抽出时间!

    ** 更新 **

    谢谢大家的建议。我试着找到是否会有一个文件 普通.h 在我的包含路径中的其他地方,可能会以某种方式包含。。。而我没有找到任何会在编译过程中滑落的东西,而不是本地的 普通.h ( 信号 )我找到了一些 .ghc 文件位于我的源文件夹中。因为他们没有被 make clean ,我手动删除了那些文件。你猜怎么着?没有警告。这些文件是什么?为什么要创建它们?

    4 回复  |  直到 15 年前
        1
  •  4
  •   paxdiablo    15 年前

    首先,我不认为给予 common.h 对于makefile中的编译器:

    @$(CC) $(C_FLAGS) -c sgbd_server.c common.h
    

    最好是:

    @$(CC) $(C_FLAGS) -c sgbd_server.c
    

    头文件通常与 #include . 你似乎在告诉编译器尝试编译 普通.h 作为一个独立的C文件。这是客户机和服务器编译命令之间的一个区别,您应该修复它。

    我唯一能建议的是你可能没有得到你的头文件 认为 你得到了。从写这句话开始:

    #error Urk! in common.h
    

    在你的顶端 普通.h 并确保构建在那里失败。

    如果没有,那么这个文件来自其他地方。你也可以用你的 sgbd_server.h 文件也一样。


    根据您的编辑:

    我在源文件夹中找到了一些.ghc文件。因为它们不是通过make clean来清理的,所以我手动删除了那些文件。你猜怎么着?没有警告。这些文件是什么?为什么要创建它们?

    假设这些是 ghc 是个打字错误,你的意思是 gch ,由生成的预编译头 gcc ,至少在一定程度上加快了编译过程。在构建过程中不必多次处理头文件(每个包含它的源文件一次),只需预编译一次并使用预编译的版本会更高效。

    我认为这很可能是因为你 普通.h 在编译器命令行中执行服务器操作时。默认情况下,头文件直接提供给 海合会 将转换为预编译的头文件并在该点之后优先使用。为了测试这个,我创建了一个 qq.h 存档并执行 gcc qq.h 突然出现 qq.h.gch .

    考虑到删除它们解决了您的问题,这些文件很可能以某种方式导致了您的问题(可能是预编译的头比实际的头老,或者完全是其他原因)。很有可能您的编译行:

    @$(C C)$(C_标志)-C sgbd_server.C common.h
    

    首先编译服务器程序,包括旧的预编译头, 然后 从新的头文件中生成一个新的预编译头文件。

    这可能就是为什么 普通.h 没有(立即)效果。你必须 make ; touch common.h ; make 以确保服务器程序中使用了较新的预编译头文件。

    你是否想追根溯源,得到一个恰当的解释,这是一个品味的问题——有一个学派认为,有时你应该只是记录下你是如何修复它的,而不是太担心,以免你陷入现实本身的本质之中。

    当然不是我,我是那种试图将我的问题追溯到导致它的单个亚原子粒子的人格类型,但有时实用主义要求我放手

        2
  •  1
  •   Peter G. McDonald    15 年前

    观察:你在一个定义中有一个=我怀疑你不是有意的

    #define CLIENT_FIFO_PREFIX = "./sgbd_client_"
    

    也许应该是

    #define CLIENT_FIFO_PREFIX "./sgbd_client_"
    

    注释:当原型包含形式参数名(除了强制类型之外)并且函数的定义使用不同的形式参数名时,我偶尔会看到编译器的奇怪行为。在你的管子里 包括common.h?

    还有,有条件的警卫 标题文件名 #定义 标题文件名 #恩迪夫 是一个很好的做法,但这与你的问题没有直接关系。

    .PMCD。

        3
  •  0
  •   JOTN    15 年前

    我怀疑您可能有另一个名为common.h的文件,而不是您期望的文件。我复制并粘贴了你的文件,它编译时没有任何警告。

        4
  •  0
  •   sth    15 年前

    你发布的文件中的include看起来应该可以工作。一些想法还有什么可能是错误的:

    • 做 common.h 或 console.h 尽量包括 sgbd_server.h ,所以你最终得到了循环包含?
    • 你是否使用了包括警卫(甚至其他 #ifdef s) 也许把它们混在一起,这样其中一个文件就被无意中排除了?
    • 你还有别的吗 普通.h 在你的某个地方包含了可能被包含的路径,而不是你想要的路径?