Подтвердить что ты не робот

Как "низкий" делает C как "низкоуровневый" язык?

Мы часто слышим, что C - это язык низкого уровня, но насколько он медленный? Самый низкий уровень, о котором я знаю, - это управление памятью с помощью указателей. Есть ли еще какие-то уровни, которые мне еще предстоит обнаружить? Что означает "близко к оборудованию"? Как "близко к оборудованию" является C?

4b9b3361

Ответ 1

Используйте стандартную терминологию. Языки более высокого уровня и языки нижнего уровня.

Языки высокого уровня предназначены для удобства лица, написавшего язык.

Языки нижнего уровня предназначены для простоты компьютера, на котором запущен язык.

C - это всего лишь шаг вперед от языка ассемблера, который является фактически человеческим переводом машинного кода. Он не получает меньше машинного кода, но люди не читают шестнадцатеричный код очень хорошо, поэтому сборка считается языком программирования самого низкого уровня.

Большинство операций C могут быть переведены на менее чем десять машинных инструкций. Некоторые могут быть переведены в единую машинную инструкцию (в зависимости от многих обстоятельств). Для сравнения, многие языки высокого уровня могут потребовать от десятков до тысяч машинных инструкций для реализации конкретной операции.

"Уровень" языка - это в основном абстрактное понятие. Это не полезно для многих, кроме сравнения одного языка с другим в контексте попытки понять, нужно ли вам писать больше исходного кода в том или ином виде, или вам нужно будет больше узнать о машинной архитектуре на одном языке по сравнению к другому.

Ответ 2

C иногда называют "портативным языком ассемблера". По существу все, что вы можете сделать в сборке, вы можете сделать на C (либо через встроенные функции, либо через встроенную сборку).

Ответ 3

C - это нечто большее, чем процедурная оболочка вокруг ASM. Хороший программист на C, который знает, что стоит за этим языком, должен иметь возможность взглянуть на фрагмент кода и записать ASM, в который будет скомпилирован код. Эти инструкции ASM могут быть переведены в 1:1 на двоичные машинные инструкции. Это почти на один шаг выше сборки, и поэтому вы можете написать код C, который делает ЧТО-НИБУДЬ, на котором способен компьютер, НО, находясь на таком низком уровне, он относительно примитивен с точки зрения того, о чем вы должны быть конкретным. Например, память рассматривается как таковая, а не абстрагируется в конструкциях, таких как "куча". Создание "нового" объекта на языке OO так же просто, как и так; эквивалентный C-код будет включать в себя malloc для суммы размера всех членов этого объекта и указывает на каждый из членов объекта внутри блока.

Ответ 4

Лицо, создающее оборудование (процессор, материнская плата и т.д.), также предоставляет свой машинный язык (язык ассемблера). Это становится самым низким уровнем. Затем какой-то другой человек пишет компилятор для C, который преобразует синтаксис Си в собственный язык ассемблера для этого оборудования (пожалуйста, поправьте меня, если я ошибаюсь). С помощью C вы можете использовать сборку, и достигнут самый низкий уровень!

Ответ 5

Определение "low" немного сложно, но C поддерживает ряд системных вызовов, gotos и даже сборку, перемещая через расширения.

Ответ 6

Вам нужно определить, что вы подразумеваете под низким уровнем, чтобы ответить на этот вопрос.

C позволяет вам делать все, что вы могли бы сделать с помощью сборки, но не все. Если вы хотите сделать что-то странное/частное/необычное, вам может понадобиться использовать сборку, хотя для большинства (/все?) Реальных целей C будет более чем достаточно, если у вас есть хороший компилятор для вашего оборудования.


РЕДАКТИРОВАТЬ: это немного подробнее...

C не дает вам никаких гарантий относительно инструкции по сборке, в которую он будет скомпилирован, и дает только частичные указания об объектах, которые будут выделены в памяти.

В общем случае, если вам нужно иметь материал в памяти определенным образом, если вам нужна определенная последовательность команд сборки для запуска, вам, вероятно, придется использовать какой-то другой язык (возможно, сборку напрямую), в противном случае в целом C будет хорошо.

Конечно, мы можем найти столько особых случаев, сколько хотим: если у вас есть специальные операции с сборкой, которые позволяют вам придумывать материал высокого уровня, C, вероятно, не сможет их использовать.

Считается, что

C заменяет сборку на обычных (возможно, я мог бы сказать, общих) процессорах, она не будет идеальна для процессоров с собственной функциональной сборкой или во многих других контекстах.


Вы не можете просто сказать "как уровень C?", вам нужно сделать обратное: определить, какой материал низкого уровня вам нужен, а затем посмотреть, может ли C это сделать.

Ответ 7

Память, которую вы можете использовать для ОС общего назначения, обычно виртуальная память, поэтому обычно это мошенничество - ваши C-указатели не содержат адреса физической памяти, там весь слой глубже.

Ниже вы должны запрограммировать MMU, что нелегко сделать на C, для этого обычно требуется сборка, зависящая от архитектуры, и ваш код должен запускаться в виде привилегированного mode (как это делает ядро ​​ОС)

Также могут быть различные другие сопроцессоры или весь диапазон наборов инструкций, это может быть трудно получить непосредственно в C.

Ответ 8

Главное, что C затеняет, насколько это вообще затеняет, - это управление потоком, в нескольких случаях. Единственное, что я когда-либо писал в сборке, которая не очень хорошо переводилась на C, заключалась в том, что он прыгал в блок кода в произвольной точке, выполняя его с этой позиции, периодически проверяя определенное состояние состояния и обнаруживая необходимость, сохраняя текущее местоположение программы где-то и выход. Затем в следующий раз я отскочил назад в том же положении, что и последний блок кода. Кооперативные сопрограммы, я думаю, вы бы назвали их.

Решение C должно было использовать два отдельных потока, обмениваясь семафорами. Но потоки не являются частью самого языка C.

Ответ 9

C сегодня используется во многих случаях как "язык переносимых ассемблеров", потому что семантика языка может быть в значительной степени просто тонким шпоном над базовой машинной архитектурой.

В прошлом было довольно просто смотреть строки C-кода и иметь представление о том, что будет на самом деле машинный язык, который будет генерировать код C.

При использовании в целом вместе со своей окружающей средой разработки прямолинейно иметь идеальный контроль над компоновкой памяти структур данных и общим размещением памяти. Разумеется, такой C-код в целом не переносится, поскольку он опирается на детали реализации компилятора, которые стандарт C позволяет гибко и на основе реализации. Но в целом сам код C может быть МОСТНО портативным. Это аспект языка - это то, что привело к его популярности в таких системах, как Unix, позволяя основной части ОС быть переносимой на всех машинах с минимальными специфическими для реализации конкретными аспектами реализации, которые, возможно, являются языком ассемблера.

Сегодня, с современными компиляторами и их оптимизациями, C может быть менее буквальным. То, что вы видите в коде C, не может быть переведено буквально на то, что вы получаете в сборке, из-за фактической оптимизации, сделанной компилятором.

Простым надуманным примером является что-то вроде:

int func(int a, int b) {
    int c;
    int d;

    d = 10;
    return a * d;
}

В простом компиляторе реализация может хорошо выделить 4 int в стеке, 2 для аргументов и 2 для рабочих переменных. Очевидная оптимизация заключается в том, чтобы не выделять переменную 'c' вообще, поскольку она не используется. Дальнейшая оптимизация - игнорировать "d", а также использовать константу 10. И даже более умный компилятор может хорошо видеть, как этот func используется и встроить его автоматически в вызывающую функцию, полностью исключив вызов подпрограммы.

Итак, с одной стороны, вы можете увидеть код и сказать "это то, как он будет выглядеть в сборке", и, таким образом, рассматривать его как оболочку низкого уровня поверх сборки. С другой стороны, вы можете оптимизировать современные компиляторы, чтобы они были менее буквальными, сохраняя при этом семантику того, что вы выражаете в коде, если не фактическая идеальная реализация.

Ответ 10

То, что я подразумеваю под низким уровнем, - это то, что каждый означает, когда говорят, что C - язык низкого уровня. Если бы я знал, что мне не нужно будет задавать вопрос. - ecounysis 27 секунд назад

Не похоже, чтобы вопрос выглядел вообще.

Если то, что вы хотите знать, означает то, что означает "низкий уровень", когда говорят, что в вики есть статьи, которые вы можете прочитать.

http://en.wikipedia.org/wiki/Low-level_programming_language

http://en.wikipedia.org/wiki/High-level_programming_language

Когда они говорят, что C - это язык низкого уровня, они не говорят ни о какой степени. Либо язык имеет более высокий уровень, либо низкий уровень. Это два разных типа или категории.

Ответ 11

Как насчет register? Ключевое слово в объявлении локальной переменной, которое просит компилятор сохранить его в регистре CPU, хотя может игнорировать ваше предложение.

Однако GNU C расширяет это до точки, где вы можете указать конкретный регистр, который вы хотите использовать!

register int foo asm ("a5");

Ответ 12

Тот факт, что вы задаете этот вопрос, выражает вашу наивность предмета. Это просто не так просто.

C не имеет полного гибкого языка ассемблера, но он приближается. Отсутствуют такие функции, как Tail Recursion

Но для большинства целей C делает все, что вам нужно - возможно, -