C предупреждение: неявное объявление функции - PullRequest
1 голос
/ 16 ноября 2010

Да, этот вопрос задавался много раз, и я искал и читал форумы и ТАК сообщения, но ответы на этот вопрос не имеют никакого отношения (или они так кажутся).Итак, у меня есть этот основной файл:

- 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"

** NOTE **: файл console.c и реализует некоторые функции для управления вводом / выводом на консоли, ничего сложного.Как видите, он также скомпилирован отдельно.

Теперь, когда я набираю 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 ... Что мне здесь не хватает?

Спасибо за ваше время!

** ОБНОВЛЕНИЕ **

Спасибо всем за ваше предложение.Я попытался найти, будет ли где-нибудь еще в моем пути включения файл common.h, который каким-то образом будет включен ... Хотя мне не удалось найти файл, который проскользнул в процессе компиляции вместо локального common.h ( sig ) Я обнаружил несколько .ghc файлов в моей исходной папке.Поскольку они не очищены make clean, я удалил эти файлы вручную.Угадай, что?Нет предупрежденияЧто это за файлы и почему они созданы?

Ответы [ 4 ]

4 голосов
/ 16 ноября 2010

Для начала, я не думаю, что будет хорошей идеей давать common.h компилятору в make-файле:

@$(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, чтобы убедиться, что более новый предварительно скомпилированный файл заголовка был использован в программе сервера.

Если вы хотите отследить это до первопричины и получить правильное объяснение, это вопрос вкуса - есть школа мысли, что вы должны иногда просто записывать, как вы это исправили и не беспокоиться слишком сильно, чтобы не запутаться в самой природе самой реальности.

Не я, конечно, я тип личности, который будет пытаться отследить мои проблемы до отдельной субатомной частицы, которая вызвала ее, но иногда прагматизм требует, чтобы я отпустил это: -)

1 голос
/ 16 ноября 2010

наблюдений: у вас есть = в #define, который, я подозреваю, вы не хотите иметь там

#define CLIENT_FIFO_PREFIX = "./sgbd_client_"

должно быть

#define CLIENT_FIFO_PREFIX "./sgbd_client_"

комментарии: яиногда наблюдалось странное поведение компиляторов, когда прототип содержит формальные имена параметров (в дополнение к обязательным типам), а в определении функции используются разные формальные имена параметров.то есть.в вашем pipe.c Включает ли ваш pipe.c файл common.h?

Кроме того, условные средства защиты #ifndef headerfilename #define headerfilename #endif являются хорошей практикой,но это не имеет прямого отношения к вашей проблеме.

.PMCD.

0 голосов
/ 16 ноября 2010

Включения в размещенные вами файлы выглядят так, как будто они должны работать. Несколько идей, что еще может быть не так:

  • Пытается ли common.h или console.h включить sgbd_server.h, чтобы в итоге вы получили циклические включения?
  • Используете ли вы включающие охранники (или даже другие #ifdef с) и, возможно, перепутали их где-нибудь, чтобы один из файлов был исключен непреднамеренно?
  • Есть ли у вас другой common.h где-нибудь в вашем списке включаемый путь, который может быть включен вместо того, который вы намеревались?
0 голосов
/ 16 ноября 2010

Я подозреваю, что у вас может быть другой файл с именем common.h, который будет включен вместо ожидаемого файла.Я скопировал и вставил ваши файлы, и он скомпилирован без предупреждения.

...