Comparando caracteres não assinados e EOF

quando o código a seguir é compilado, ele entra em um loop infinito:

int main()
{
    unsigned char  ch;
    FILE *fp;
    fp = fopen("abc","r");
    if(fp==NULL)
    {
        printf("Unable to Open");
        exit(1);
    }
    while((ch = fgetc(fp))!=EOF)
    printf("%c",ch);
    fclose(fp);
    printf("\n",ch);
    return 0;
}

compilador gcc também avisa sobre a compilaçã

abc.c:13:warning: comparison is always true due to limited range of data type

o código funciona bem quandounsigned char é substituído porchar ouint conforme o esperado, ou seja, termina.
Mas o código também funciona bem paraunsigned int também. como eu tenho lido emEOF é definido como-1 dentrostdio.h então por que esse código falha em caracteres não assinados, mas funciona bem em int não assinad

questionAnswers(6)

yourAnswerToTheQuestion