Четкий учебник, объясняющий модульное программирование на C? - PullRequest
2 голосов
/ 19 февраля 2010

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

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


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

Обновление 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;
}

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

В aStruct.h: 10

  • field 'ssTest 'имеет неполный тип

В main.c: 8

  • неиспользуемая переменная `asTest' (это имеет смысл)

Ответы [ 3 ]

3 голосов
/ 19 февраля 2010

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

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

/* Your code here ... */

#endif /* header_h_ */

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

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

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

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

2 голосов
/ 20 февраля 2010

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

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

0 голосов
/ 19 февраля 2010

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

previous declaration сообщение указывает на конфликтующее объявление.

...