Почему не происходит ошибки при объявлении переменной в .h файле?
Так можно делать в С, это tentative definition, объект обявленный таким образом попадает в область общих данных. При линковке одноимённые объекты в этой области становятся одним объектом.
В С++ так делать нельзя.Правильно в хедере писать extern int var, а объявление делать в каком-либо .с файле
extern int var -- это и есть объявление. Правильно определение делать в одном .c файле.
Не знаю, в какой литературе что запрещено, а у нас в gcc вот как:sashka@cellar ~ cat test.h 
int i;
sashka@cellar ~ cat test.c
#include "test.h"
#include <stdio.h>

int main (void) {
i = 10;
printf("%i\n", i);
return 1;
}
sashka@cellar ~ gcc test.c -o test.out
sashka@cellar ~ ./test.out
10
sashka@cellar ~