5

Lets say we have a few C source files such as file1.c, file2.c and main.c. We have functions as:

file1.c
      |---> file1Func1()
      |---> file1Func2()

file2.c
      |---> file2Func1()
      |---> file2Func2()

and the main file uses these functions. Now it would be natural that I create and add respective function prototype in header files file1.h and file2.h, then include these headers in main.c to use the functions.

What if I have a very large project with over thousand source (C) files, should I always create a header (then add function prototype) for every source file. Then include the header to use the functions?

Or using extern for using a function defined elsewhere (in some other source file) and rely on linker to search and fetch the function from the object file during link time?

Note: using the latter approach triggers MISRA warning of no function prototype.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Osaid
  • 557
  • 1
  • 8
  • 23

3 Answers3

10

All functions that are part of the interface, that is functions which is called by another module, should have function prototypes in the header file. Preferably together with comments documenting how that function should be used.

Functions that are not part of the interface and only used internally within the file should not have a prototype in the header. For such functions, declare the prototype at the top of the c file, and declare it as static.

This is how all (professional) C programs are written. As a side-note, this sound design is also required by MISRA-C.

There should never be a reason for you to use the extern keyword for functions. Note that a function prototype like

void func (void);

is completely equivalent to

extern void func (void);

If you need to use a function, include the relevant header.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • While I agree with you about equivalence, I prefer to see the `extern` keyword as this shows explicitly the global nature. Mind you, I prefer the C++ terminology of public/private over extern/static – Andrew Jul 05 '16 at 12:10
  • 1
    @Andrew It is mainly a matter of style. Some like to be explicit, some think it is superfluous. However, C11 future language directions say that "Declaring an identifier with internal linkage at file scope without the static storage class specifier is an obsolescent feature." So I suppose that in future C standards, we may not be able to declare functions without using extern. I very much doubt the committee dares to take that step though, since it would break so much existing code. I think the rationale here is to disallow such identifiers of object type, that is: "globals". – Lundin Jul 05 '16 at 13:27
  • Indeed... and there are more important things to fix, notwithstanding WG14's obsession with backward-compatibility! – Andrew Jul 12 '16 at 06:01
1

What if I have a very large project with over thousand source (c) files, should I always create a header (then add function prototype) for every source file. Then include the header to use the functions?

The short answer is "Yes".

The slightly longer answer is "Yes but you may omit functions from header files that are implementation details of other functions in a source file".

Declaring functions in header files and #includeing the header files makes sure that function definitions and function calls stay in sync. Otherwise, it is easy to make mistakes and those mistakes are caught at link time instead of at compile time.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

should I always create a header (then add function prototype) for every source file.

The TL;DR; answer is Yes.

My personal opinion (and one that has been written into several company coding standards) is that each C Source file should have its own associated Header file to define the external interface.

Together, the C Source file and its associated Header file define the module - but only the Header file declares the interface.

All global objects (including function prototypes) should be declared in header file; I also advocate that the extern keyword should never(*) be used in a C Source file as this is (IMHO) breaking the declared interface for the module.

{*} OK, never is a strong word, and there may be exceptions... but they should be few and far between.

Andrew
  • 2,046
  • 1
  • 24
  • 37