In C, se si definisce una funzione in un file di intestazione, tale funzione verrà visualizzata in ciascun modulo che viene compilato che include quel file di intestazione e verrà esportato un simbolo pubblico per la funzione. Quindi, se la funzione additup è definita in header.h e foo.c e bar.c includono entrambi header.h, allora foo.o e bar.o includeranno entrambi copie di additup.
Quando vai a collegare insieme questi due file di oggetti, il linker vedrà che il simbolo additup è definito più di una volta e non lo consentirà.
Se si dichiara che la funzione è statica, non verrà esportato alcun simbolo. I file oggetto foo.o e bar.o conterranno entrambi copie separate del codice per la funzione e saranno in grado di usarli, ma il linker non sarà in grado di vedere alcuna copia della funzione, quindi non si lamenterà. Ovviamente, nessun altro modulo sarà in grado di vedere la funzione. E il tuo programma sarà gonfiato con due copie identiche della stessa funzione.
Se dichiari solo la funzione nel file di intestazione, ma non la definisci, e poi la definisci in un solo modulo, il linker vedrà una copia della funzione e ogni modulo nel tuo programma sarà in grado di vederla e usalo. E il tuo programma compilato conterrà solo una copia della funzione.
Quindi, puoi avere la definizione della funzione nel file di intestazione in C, è solo cattivo stile, cattiva forma e una cattiva idea a tutto tondo.
(Con "dichiarare" intendo fornire un prototipo di funzione senza un corpo; con "definisci" intendo fornire il codice effettivo del corpo della funzione; questa è la terminologia C standard.)