views:

446

answers:

3

I'm just getting started with modular programming in C. I think I'm doing something wrong with the inclusions, because I'm getting a lot of conflicting types for 'functionName' and previous declaration of 'functionName' was here errors. I did put inclusion guards in place.

Do you know a clear tutorial that explains modular programming in C, especially how the inclusions work?


Update: I have tried to isolate my issue. Here's some code, as requested.

Update 2: updated code is below. The errors have been updated, too.

/*
 * 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;
}

This generates the following error messages:

At aStruct.h:10

  • field 'ssTest' has incomplete type

At main.c:8

  • unused variable `asTest' (this one makes sense)
+3  A: 

The base of inclusion is to make sure that your headers are included only once. This is usually performed with a sequence like this one:

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

/* Your code here ... */

#endif /* header_h_ */

The second point is to take care of possible name conflicts by handling manually pseudo namespaces with prefixes.

Then put in your headers only function declarations of public API. This may imply to add typedefs and enums. Avoid as much as possible to include constant and variable declarations: prefer accessor functions.

Another rule is to never include .c files, only .h. This is the very point of modularity: a given module dependant of another module needs only to know its interface, not its implementation.

A for your specific problem, aStruct.h uses struct smallerStruct but knows nothing about it, in particular its size for being able to allocate an aStruct variable. aStruct.h needs to include smallerStruct.h. Including smallerStruct.h before aStruct.h in main.c doesn't solve the issue when compiling aStruct.c.

mouviciel
I did remember to include the inclusion guard.
Pieter
just be careful, don't just copy paste this to your code. Make sure _header_ is renamed to something resembling your header's name.
Doug T.
Also, isn't it naughty to have an underscore as the first character of an include guard (or any identifier)? Those identifiers are reserved, aren't they? I always use "FILENAME_H_" - the trailing underscore is legal.
Steve314
@steve314: Agreed, I edited my code.
mouviciel
This answer cannot explain the "conflicting types" error message.
Hans Passant
No answer can explain the "conflicting types" error message without more information about the context. Moreover the question is about a general tutorial, not about that specific error.
mouviciel
A: 

Such errors mean that function declaration (return type or parameter count/types) differs from other function declarations or function definition.

previous declaration message points you to the conflicting declaration.

qrdl
They're exactly the same. I made sure I include the header with the prototypes before the actual function.
Pieter
What if you don't include headers?
qrdl
+2  A: 

The multiple definition problem is most likely coming from the way you're including the code. You are using #include "aStruct.c" as opposed to #include "aStruct.h". I suspect you are also compiling the .c files into your project in addition to the #include. This causes the compiler to become confused due to the multiple definitions of the same function.

If you change the #include to #include "aStruct.h" and make sure the three source files are compiled and linked together, the error should go away.

jlin
Sorry, no luck. At aStruct.h:10 (`struct smallerStruct ssTest;`), I get the following error: `field `ssTest' has incomplete type`. And why should I #include the .h file instead of the .c file? The .c file #includes the .h file, but not the other way around. So the .c file doesn't get mentioned anywhere if I only #include its .h counterpart.
Pieter
I updated the code on the top of the page for your convenience.
Pieter
The .c files should not be mentioned in sources but in Makefile.
mouviciel
I don't use a Makefile, I'm using a Windows version of Eclipse with MinGW GCC.
Pieter