2010-02-19 2 views
2

Я только начинаю с модульного программирования на C. Я думаю, что я делаю что-то неправильно с включениями, потому что я получаю много ошибок conflicting types for 'functionName' и previous declaration of 'functionName' was here. Я поместил защитники включения на место.Открытый учебник, объясняющий модульное программирование в C?

Знаете ли вы четкое руководство, объясняющее модульное программирование на C, особенно, как работают включения?


Update: Я пытался изолировать мою проблему. Вот, пожалуйста, какой-то код.

Обновление 2: обновленный код приведен ниже. Ошибки также были обновлены.

/* 
* main.c 
*/ 
#include <stdio.h> 
#include "aStruct.h" 

int main() { 
    aStruct asTest = createStruct(); 

    return 0; 
} 

/* 
* aStruct.h 
*/ 
#ifndef ASTRUCT_H_ 
#define ASTRUCT_H_ 

struct aStruct { 
    int value1; 
    int value2; 
    struct smallerStruct ssTest; 
}; 
typedef struct aStruct aStruct; 

aStruct createStruct(); 

#endif /* ASTRUCT_H_ */ 

/* 
* smallerStruct.h 
*/ 
#ifndef SMALLERSTRUCT_H_ 
#define SMALLERSTRUCT_H_ 

struct smallerStruct { 
    int value3; 
}; 
typedef struct smallerStruct smallerStruct; 

smallerStruct createSmallerStruct(); 

#endif /* SMALLERSTRUCT_H_ */ 

/* 
* aStruct.c 
*/ 
#include <stdio.h> 
#include "smallerStruct.h" 
#include "aStruct.h" 

aStruct createStruct() { 
    aStruct asOutput; 

    printf("This makes sure that this code depends on stdio.h, just to make sure I know where the inclusion directive should go (main.c or aStruct.c).\n"); 

    asOutput.value1 = 5; 
    asOutput.value2 = 5; 
    asOutput.ssTest = createSmallerStruct(); 

    return asOutput; 
} 

/* 
* smallerStruct.c 
*/ 
#include <stdio.h> 
#include "smallerStruct.h" 

smallerStruct createSmallerStruct() { 
    smallerStruct ssOutput; 
    ssOutput.value3 = 41; 
    return ssOutput; 
} 

Это порождает следующие сообщения об ошибках:

At aStruct.h:10

  • field 'ssTest' has incomplete type

At main.c:8

  • unused variable `asTest' (this one makes sense)
+1

Не могли бы вы разместить образец кода, который дает вам проблемы? – FrustratedWithFormsDesigner

+0

Я добавил образец в соответствии с запросом. – Pieter

+1

Вам нужно # включить "lessStruct.h" в astruct.h – 2010-02-20 10:54:24

ответ

2

Проблема с множественным определением, скорее всего, происходит из-за того, что вы включаете код. Вы используете #include "aStruct.c", а не #include "aStruct.h". Я подозреваю, что вы также компилируете файлы .c в свой проект в дополнение к #include. Это заставляет компилятор запутываться из-за множества определений одной и той же функции.

Если вы изменили #include на #include "aStruct.h" и убедитесь, что три исходных файла скомпилированы и связаны друг с другом, ошибка должна исчезнуть.

+0

Простите, не повезло. В aStruct.h: 10 ('struct lessStruct ssTest;') я получаю следующую ошибку: '' 'ssTest 'имеет неполный тип'. И почему я должен # включить файл .h вместо файла .c? Файл .C# содержит файл .h, но не наоборот. Поэтому файл .c не упоминается нигде, если я только # включил его .h-копию. – Pieter

+0

Я обновил код в верхней части страницы для вашего удобства. – Pieter

+0

Файлы .c не должны упоминаться в источниках, а в Makefile. – mouviciel

3

Основание включения, чтобы убедиться, что ваши заголовки включены только один раз. Это обычно выполняется с последовательностью, как этот:

/* header.h */ 
#ifndef header_h_ 
#define header_h_ 

/* Your code here ... */ 

#endif /* header_h_ */ 

Второй пункт заботиться о возможных конфликтов имен путем обработки вручную псевдо пространств имен с префиксами.

Затем помещайте в свои заголовки только декларации функций публичного API. Это может означать добавление typedefs и перечислений. Избегайте, насколько это возможно, включать объявления констант и переменных: предпочитайте функции доступа.

Другое правило: никогда не включать файлы .c, только .h. Это сама точка модульности: данный модуль, зависящий от другого модуля, должен знать только его интерфейс, а не его реализацию.

А для вашей конкретной проблемы aStruct.h использует struct smallerStruct, но об этом ничего не знает, в частности его размер за возможность выделить переменную aStruct. aStruct.h должен содержать smallerStruct.h. В том числе smallerStruct.h до aStruct.h в main.c не решает проблему при компиляции aStruct.c.

+0

Я не помню, чтобы включить охранник включения. – Pieter

+0

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

+2

Кроме того, не стоит ли подчеркивать, что символ первого символа включенного защитника (или любого идентификатора)? Эти идентификаторы зарезервированы, не так ли? Я всегда использую «FILENAME_H_» - завершающее подчеркивание является законным. – Steve314

0

Такие ошибки означают, что декларация функции (тип возврата или количество параметров/типы параметров) отличается от других объявлений функций или определения функций.

previous declaration сообщение указывает на противоречивую декларацию.

+0

Они точно такие же. Я убедился, что я включил заголовок с прототипами до фактической функции. – Pieter

+0

Что делать, если вы не включаете заголовки? – qrdl

Смежные вопросы