cinclude

Omission of function declarations


Are there any circumstances in which it is acceptable to omit function declarations from source files? I have a C project which will not compile, and I do not know why. As far as I can determine the compiler (GCC 4.4.1) cannot find the declaration of the 'sepData' typedef when it gets to the declaration of the function 'sysData' in 'system.h'.

From sepsis.h

typedef struct {
    int16 intensity;
    int16 offset;
} sepData;

From sepsis.c

sepData sepR, sepIR;

From system.h

void sysData(sepData *sepR, sepData *sepIR);

From system.c

#include "system.h"
#include "sepsis.h"

extern sepData sepR, sepIR;

void sysData(sepData *sepR, sepData *sepIR)
{
}

If I remove the declaration of 'sysData' from 'system.h', then the project compiles without error. Not knowing a great deal about C, I thought that including such declarations was compulsory. Is anyone able to explain what is going on here?


Solution

  • #include "system.h"
    #include "sepsis.h"
    

    If system.h does not #include "sepsis.h" itself, then the type sepData will not be known when you prototype the sysData() function, and you get the error message. You can probably paper over this problem by swapping the order of the two headers:

    #include "sepsis.h"
    #include "system.h"
    

    But that only fixes this specific compilation unit. If you have other compilation units in this application, you'll need to care about the order of #include lines, which gets tiresome. Perhaps system.h needs to #include "sepsis.h" itself -- and have sepsis.h guard against multiple inclusion via the usual incantation:

    #ifndef _SEPSIS_H_
    #define _SEPSIS_H_
    ...
    #endif // _SEPSIS_H_
    

    Your codebase was able to compile without the sysData() prototype because you hadn't used the function before the function's declaration. Had you used the function before declaration, I expect the compiler would have given you a warning message and assumed every single argument should be an int and the return type should also be an int. (The old K&R rules.) This would, of course, not work, but it might not be obvious why it doesn't work. (Yay C.)