0

I am currently "playing" around in a quite big and old codebase and, quite unfortunately, it has no fixed style attached to it. So it was just made to work but that also means that quite a lot of it can be described as spaghetti code.

I came across something that I do not fully undersand. Compiler is from ARM/KEIL and it is for an embedded system.

first file:

fileA.c
// prototype
int GetSomething( int a );

// implementation
int GetSomething( int a) {
    DoSomething();
}

second file:

fileB.c
// prototype
int GetSomething( int a )

void main ( void ) {
    GetSomething(10);
}

There are no headers which have a declaration for the function GetSomething but the function is still correctly linked. Originally, there are a extern keyword in the second file in the declaration of GetSomething, but with or without that results in the same binary. The code has been tests and works.

I've seen Stackoverflow Question but that doesn't seem to cover my case as it seems to have nothing to do with the extern keyword.

I hope that somebody can explain that to me or tell me what is going on. Thanks.

  • There is nothing special about header files. They are only used to ensure that multiple files use same declarations. If you provide a correct prototype directly in your .c file then this is the same as putting it into a header file. It's just more effort to keep everything in sync. – Gerhardh Aug 16 '22 at 07:52
  • For function prototypes, `extern` is default. – Gerhardh Aug 16 '22 at 07:53
  • Header file is just text. When you write `#include` the content of the file _literally_ is replacing `#include`. You can have no headers, just paste the same stuff around. Btw, you may want to start by refactoring your codebase, so the same stuff is in headers. – KamilCuk Aug 16 '22 at 07:53
  • @Gerhardh that exlpains some parts of the whole codebase. Isn't this a bad practice to include funtions like this without headers as it might allows to circumvent any archiectures that are in place? I would guess that this is something that should be pointed out in code-reviews. – FhatTheWuck Aug 16 '22 at 08:01
  • @KamilCuk I plan on exactly doing that stuff, that's why I asked this question to avoid mistakes. – FhatTheWuck Aug 16 '22 at 08:07
  • 2
    Yes, that is poor design. In a code review I wouldn't accept code where such functions are not placed in a header that is then included both in the file where it is defined and where it is used. If you don't do that you cut your compiler's abilities to detect mismatches in declarations. – Gerhardh Aug 16 '22 at 08:13
  • 1
    I work on a codebase with a forty-year history. Before there was a standard, the was no way to enforce function signatures, and there was no `void` for return types or empty argument lists. When prototypes were added, it was easier to copy the declaration into the file than to create a header that did the job properly (or get someone on another part of the team responsible for the code that provided the service to create the header), so that's what people under time pressure did. And it becomes a major PITA when the function signature changes. Use headers! – Jonathan Leffler Aug 16 '22 at 11:57
  • Rule of thumb (according to me): Functions (and file scope variables) should be static until there is a header that declares them. Corollary: you should never need an `extern` declaration in a source file. They should only appear in headers. – Jonathan Leffler Aug 16 '22 at 12:01

1 Answers1

2

Using header files and #include directives are just a more organized and neater way to use various parts of code in a program at different places.

When you do something like #include "header.h" a copy of header.h is put into the file.

So when you write

GetSomething( int a );

you are essentially doing an alternative to what #include would normally do.

Another important detail is that function prototypes have the extern storage class specifier by default.

One thing you should keep in mind is that declaring function prototypes across your files manually can result in error prone and hard to maintain code. So it is best to utilize header files and #include directives.

programmer
  • 462
  • 1
  • 6