A resposta para sua pergunta depende de qual idioma C está sendo perguntado.
A linguagem descrita no Manual de Referência C de Dennis Ritchie, em 1974, era uma linguagem de baixo nível que oferecia algumas das conveniências de programação de linguagens de nível superior. Os dialetos derivados dessa linguagem também tendiam a ser linguagens de programação de baixo nível.
Quando o Padrão C 1989/1990 foi publicado, no entanto, ele não descreveu a linguagem de baixo nível que se tornou popular na programação de máquinas reais, mas descreveu uma linguagem de nível superior que poderia ser - mas não era necessário - implementado em termos de nível inferior.
Como observam os autores da Norma C, uma das coisas que tornou a linguagem útil foi o fato de muitas implementações poderem ser tratadas como montadoras de alto nível. Como o C também era usado como uma alternativa a outras linguagens de alto nível e como muitos aplicativos não exigiam a capacidade de fazer coisas que as linguagens de alto nível não podiam fazer, os autores do Padrão permitiram que as implementações se comportassem de maneira arbitrária. se os programas tentassem usar construções de baixo nível. Conseqüentemente, a linguagem descrita pelo Padrão C nunca foi uma linguagem de programação de baixo nível.
Para entender essa distinção, considere como o Ritchie's Language e o C89 visualizariam o trecho de código:
struct foo { int x,y; float z; } *p;
...
p[3].y+=1;
em uma plataforma em que "char" é 8 bits, "int" é big-endian de 16 bits, "float" é de 32 bits e as estruturas não têm requisitos especiais de preenchimento ou alinhamento, portanto o tamanho de "struct foo" é de 8 bytes.
No idioma de Ritchie, o comportamento da última instrução pegaria o endereço armazenado em "p", acrescentaria 3 * 8 + 2 [ie 26] bytes a ele e buscaria um valor de 16 bits nos bytes naquele endereço e no próximo , adicione um a esse valor e, em seguida, escreva de volta esse valor de 16 bits nos mesmos dois bytes. O comportamento seria definido como ação nos bytes 26 e 27 após o endereço p, sem levar em consideração o tipo de objeto armazenado lá.
Na linguagem definida pelo Padrão C, no caso de * p identificar um elemento de uma "estrutura foo []" que é seguida por pelo menos três elementos mais completos desse tipo, a última instrução adicionaria um ao membro y de o terceiro elemento após * p. O comportamento não seria definido pela Norma em nenhuma outra circunstância.
A linguagem de Ritchie era uma linguagem de programação de baixo nível porque, embora permitisse ao programador usar abstrações como matrizes e estruturas quando conveniente, definia o comportamento em termos do layout subjacente dos objetos na memória. Por outro lado, a linguagem descrita pelos padrões C89 e posteriores define as coisas em termos de uma abstração de nível superior e apenas define o comportamento do código que é consistente com isso. Implementações de qualidade adequadas para programação de baixo nível se comportarão de maneira útil em mais casos do que as exigidas pela Norma, mas não há documento "oficial" especificando o que uma implementação deve fazer para ser adequada a esses propósitos.
A linguagem C inventada por Dennis Ritchie é, portanto, uma linguagem de baixo nível e foi reconhecida como tal. A linguagem inventada pelo Comitê de Padrões C, no entanto, nunca foi uma linguagem de baixo nível na ausência de garantias fornecidas pela implementação que vão além dos mandatos da Norma.