Столкновение с ошибкой Конфликт типа данных, но не может найти конфликт - PullRequest
2 голосов
/ 27 марта 2019

Я объявил функцию в file_utils.h и определил ее в file_utils.c. Во время компиляции она выдает ошибку конфликтующего типа.

File_utils.h

    #ifndef FILE_UTILS_H
    #define FILE_UTILS_H

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    #include <sys/types.h>

    #ifdef HAVE_DIRENT_H
    #include <dirent.h>
    #define NAMLEN(dirent) strlen((dirent)->d_name)

    #else

    #define dirent direct
    #define NAMLEN(dirent) ((dirent)->d_namlen)
    #ifdef HAVE_SYS_NDIR_H
    #include <sys/ndir.h>
    #endif

    #ifdef HAVE_SYS_DIR_H
    #include <sys/dir.h>
    #endif

    #ifdef HAVE_NDIR_H
    #include <ndir.h>
    #endif

    #endif


    bool is_relative_path(struct dirent *ent);

File_utils.c

    #include "file_utils.h"
    #include <stdbool.h>
    #include <dirent.h>

    bool is_relative_path(struct dirent *ent){
        return (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0);
     }

Ошибка:

abhiram@abhiram-Lenovo-G50-70:~/libpostal-master/src$ gcc -DLIBPOSTAL_DATA_DIR='"$//home/abhiram/libpostal-master/data"' -o main main.c libpostal.c file_utils.c json_encode.c string_utils.c -std=c99 -w     
file_utils.c:45:6: error: conflicting types for ‘is_relative_path’
bool is_relative_path(struct dirent *ent){
     ^
In file included from file_utils.c:1:0:
file_utils.h:59:6: note: previous declaration of ‘is_relative_path’ was here
bool is_relative_path(struct dirent *ent);
     ^

Я включил библиотеки dirent.h и stdbool.h.

Ответы [ 4 ]

2 голосов
/ 27 марта 2019
  1. Разрешить все предупреждения компилятора.
  2. Компилировать со всеми включенными предупреждениями компилятора -Wall -Wextra.
  3. Разрешить все предупреждения компилятора.
  4. В коде, который вы разместили, отсутствует #endif, возможно, от #ifdef HAVE_DIRENT_H, но я предполагаю, что последняя строка file_utils.h должна быть закрывающей #endif.
  5. Предупреждение, которое я получаю от gcc, таково:

предупреждение: "struct direct" объявлено внутри списка параметров
предупреждение: его область действия - только это определение или декларация, что, вероятно, не то, что вам нужно

Это самое важное предупреждение.

Определение структуры действительно только внутри списка параметров функции. Пример:

void other_f(
   struct B a // this will forward declare struct B
   // scope of this variable is _only_ inside function parameter list
); // here struct B get's out of scope!
struct B b; // will error, there is no struct B here
// struct B was declared inside function parameter list
// you can't use it anywhere else

MCVE к вашей проблеме будет следующим примером:

void f(struct A);
struct A;
void f(struct A); // error conflicting types for 'f'

struct A будет объявлено (я называю это "автоматически объявленным") в списке параметров функции void f( <here> ) при первом использовании. Объявление структуры будет видно только внутри списка параметров. Так что это похоже на псевдокод:

{
   struct A; // type only valid inside `{` `}` braces
   void f(struct A a); // imagine this symbol is visible outside `{` `}`
}

т. struct A не виден за пределами { }.

Затем вы объявляете еще один struct A:

struct A;
void f(struct A a);

Но этот struct A отличается от других struct A. В отличие от struct A, функция f отличается, компилятор выдает ошибку.

Не считайте ваш заголовок:

#define dirent direct
...
bool is_relative_path(struct dirent *ent);

Я не знаю, является ли direct опечаткой или нет. Но вам нужно объявить вперед struct direct, чтобы прямое объявление struct direct было видно вне списка параметров функции is_relative_path.

struct direct;
#define dirent direct
...
// or here:
struct dirent;
bool is_relative_path(struct dirent *ent);
1 голос
/ 27 марта 2019

Похоже, ваша проблема в порядке включения файла, если "File_utils.c" и / или отсутствует определение HAVE_DIRENT_H.

В данном порядке включения "file_utils.h" понятия не имеет, что такое struct dirent, поскольку (предположительно HAVE_DIRENT_H) определено в <dirent.h>. Если это НЕ так, просто убедитесь, что HAVE_DIRENT_H IS определено, прежде чем включать "file_utils.h"

Чистый эффект как есть в коде состоит в том, что в "file_utils.h", bool is_relative_path(struct dirent *ent) фактически рассматривается как bool is_relative_path(some_pointer_to_an_unknown_struct_type ent), тогда как "file_utils.c" видит сигнатуру функции как bool is_relative_path(a_pointer_to_a_struct_type_i_definately_know_about ent).

Таким образом, два файла НЕ согласуются в сигнатуре функции.

Редактировать

@n.m. верно в том, что "file_utils.h", по сути, видит четкое определение struct dirent, и что нельзя объявить тип в списке параметров функции.

TLDR

Отредактируйте File_utils.c, чтобы определить HAVE_DIRENT_H и / или #include <dirent.h> до #include "file_utils.h", чтобы и "file_utils.h", и "file_utils.c" видели сигнатуру общей функции для bool is_relative_path(struct dirent *ent)

0 голосов
/ 27 марта 2019

Вы не можете объявить тип в списке параметров функции. Это то, что происходит, когда в File_utils.h у вас есть объявление is_relative_path без предварительного объявления stuct dirent.

Либо #include <dirent.h> в File_utils.h (рекомендуется), либо добавьте объявление

struct dirent;

где-то в нем выше is_relative_path.

0 голосов
/ 27 марта 2019

Похоже, что объявление bool is_relative_path(struct dirent *ent); - ПОСЛЕ объявления #endif препроцессора (включая охранники).Это означает, что включение этого заголовочного файла в два разных файла приведет к двум объявлениям.Посмотрите на это: https://en.wikipedia.org/wiki/Include_guard, чтобы получить более подробную информацию

Это должно исправить это:

#ifndef FILE_UTILS_H
#define FILE_UTILS_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>

#ifdef HAVE_DIRENT_H
#include <dirent.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)

#else

#define dirent direct
#define NAMLEN(dirent) ((dirent)->d_namlen)
#ifdef HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif

#ifdef HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif

#ifdef HAVE_NDIR_H
#include <ndir.h>
#endif

// moved the declaration between the #ifndef #endif block
bool is_relative_path(struct dirent *ent);

#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...