Ответ на ваш вопрос зависит от того, о каком языке C он спрашивает.
Язык, описанный в Справочном руководстве С 1974 года Денниса Ритчи, был языком низкого уровня, который предлагал некоторые удобства программирования языков высокого уровня. Диалекты, производные от этого языка, также, как правило, были языками программирования низкого уровня.
Однако, когда был опубликован стандарт С 1989/1990 гг., Он не описывал язык низкого уровня, ставший популярным для программирования на реальных машинах, а вместо этого описывал язык более высокого уровня, который мог бы быть - но не обязателен - - реализовано в терминах более низкого уровня.
Как отмечают авторы стандарта C, одна из вещей, которая сделала язык полезным, заключалась в том, что многие реализации можно рассматривать как ассемблеры высокого уровня. Поскольку C также использовался в качестве альтернативы другим языкам высокого уровня, и поскольку многим приложениям не требовалась способность делать то, чего не могли делать языки высокого уровня, авторы стандарта позволили реализациям вести себя произвольным образом. если программы пытались использовать низкоуровневые конструкции. Следовательно, язык, описанный в Стандарте C, никогда не был языком программирования низкого уровня.
Чтобы понять это различие, рассмотрим, как язык Ричи и C89 будут просматривать фрагмент кода:
struct foo { int x,y; float z; } *p;
...
p[3].y+=1;
на платформе, где «char» равен 8 битам, «int» равен 16 битам с прямым порядком байтов, «float» равен 32 битам, и структуры не имеют специальных требований к заполнению или выравниванию, поэтому размер «struct foo» составляет 8 байтов.
На языке Ричи поведение последнего оператора будет принимать адрес, сохраненный в «p», добавлять к нему 3 * 8 + 2 [то есть 26] байта и извлекать 16-битное значение из байтов по этому адресу и следующему добавьте единицу к этому значению, а затем запишите это 16-битное значение в те же два байта. Поведение будет определяться как действие на 26-й и 27-й байты, следующие за байтом по адресу p, независимо от того, какой тип объекта там хранится.
На языке, определенном Стандартом C, в случае, если * p идентифицирует элемент «struct foo []», за которым следуют как минимум еще три полных элемента этого типа, последний оператор добавит один к члену y из третий элемент после * р. Поведение не будет определяться Стандартом ни при каких других обстоятельствах.
Язык Ричи был языком программирования низкого уровня, потому что, хотя он позволял программисту использовать абстракции, такие как массивы и структуры, когда это было удобно, он определял поведение в терминах базовой структуры объектов в памяти. В отличие от этого, язык, описанный в C89 и более поздних стандартах, определяет вещи в терминах абстракции более высокого уровня и определяет только поведение кода, которое соответствует этому. Качественные реализации, подходящие для низкоуровневого программирования, будут вести себя полезно в большем количестве случаев, чем предписано Стандартом, но не существует «официального» документа, определяющего, что реализация должна делать, чтобы подходить для таких целей.
Таким образом, язык Си, изобретенный Деннисом Ритчи, является языком низкого уровня и был признан таковым. Тем не менее, язык, изобретенный Комитетом по стандартам C, никогда не был языком низкого уровня в отсутствие предоставленных реализацией гарантий, выходящих за рамки мандатов Стандарта.