In C, se si definisce una funzione in un file di intestazione, tale funzione verrà visualizzata in ogni modulo compilato che include tale file di intestazione e un simbolo pubblico verrà esportato per la funzione. Quindi se la funzione additup è definita in header.h, e foo.c e bar.c entrambi includono header.h, quindi foo.o e bar.o includeranno entrambe le copie dell'additup.
Quando vai a collegare insieme questi due file oggetto, il linker vedrà che l'additup dei simboli è definito più di una volta e non lo permetterà.
Se dichiari che la funzione è statica, non verrà esportato alcun simbolo. I file oggetto foo.o e bar.o continueranno a contenere entrambe 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 lamenteranno Naturalmente, nessun altro modulo sarà in grado di vedere la funzione. E il tuo programma sarà gonfio di due copie identiche della stessa funzione.
Se dichiari la funzione solo 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 del tuo programma sarà in grado di vederlo e usarlo. 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.
(Per "dichiarare", intendo fornire un prototipo di funzione senza un corpo, con "define" intendo fornire il codice effettivo del corpo della funzione, questa è la terminologia C standard).