Как «низкий» делает C как «низкоуровневый» язык? [закрыто]

17

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

    
задан ecounysis 16.02.2011 в 19:00
источник
  • «Язык программирования C - язык, который сочетает гибкость языка ассемблера с властью языка ассемблера». –  Marc B 16.02.2011 в 19:02
  • ассемблерный язык с c? –  Mr Coder 16.02.2011 в 19:03
  • @jason courses.engr.illinois.edu/ece390/books/labmanual/... –  Kevin Sylvestre 16.02.2011 в 19:04
  • C ударил меня segfault, не дал мне никаких сообщений об ошибках, а затем рассмеялся мне в лицо. Я думал, что это довольно низко :( –  corsiKa 16.02.2011 в 19:05
  • @ecounysis Более высокий уровень обычно означает меньше необходимости знать об оборудовании. Файловая система более высокого уровня, чем контроллер жесткого диска. Набор инструментов командной строки, таких как cp (copy), ls (dir) и т. Д., Является более высоким, чем файловая система. Графический диспетчер файлов рабочего стола (например, nautilus / midnight commander / explorer) является более высоким, чем набор инструментов командной строки. Самый низкий уровень - это прямое аппаратное сопряжение, поскольку оно не представляет собой абстракцию аппаратного обеспечения «более высокого уровня»: это аппаратное обеспечение. –  Edwin Buck 16.02.2011 в 21:37
Показать остальные комментарии

12 ответов

21

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

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

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

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

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

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

    
ответ дан Edwin Buck 16.02.2011 в 19:08
источник
  • Линус начал кодирование в «машинный код» / сырые инструкции. Только потом он понял, что есть нечто, называемое ассемблером;) –  Runium 31.10.2013 в 00:30
5

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

    
ответ дан bta 16.02.2011 в 19:04
источник
  • Конечно, встроенная сборка не является частью языка C. –  eq- 16.02.2011 в 19:07
  • @ eq- Правда, ключевое слово asm официально не является частью стандарта (оно упоминается только как «общее расширение»). Однако практически каждый компилятор поддерживает некоторую форму встроенной сборки. Если вы можете получить указатель на адресное пространство, в котором находится ваш код, вы можете написать самомодифицирующийся код, который вводит произвольные команды сборки (во время выполнения) с использованием стандартных конструкций на языке C. –  bta 16.02.2011 в 19:13
  • Нет. См. мой ответ Кейту. –  Ira Baxter 16.02.2011 в 19:16
  • @ eq- Если вы можете получить такой указатель, вы можете сделать все это с любого языка с указателями, например, Pascal. Я делал это с помощью команды POKE на компьютерах TRS80 в BASIC. –  Ira Baxter 16.02.2011 в 19:17
  • Я думаю, что Ира имела в виду @bta. QEMU на самом деле действительно интересный проект для этого обсуждения; это динамический эмулятор рекомпиляции, который написан без зависимостей от целевой архитектуры. Он достигает того, что через глобальные переменные функции C выполняют эмулированные инструкции и перемещаются с указателей функций на фактический код внутри функции, например, чтобы захватить скомпилированный материал во время выполнения и сшить его вместе. Таким образом, он делает допущения за пределами спецификации C и, следовательно, не является технически допустимым C, но работает на практике в разных машинах и компиляторах. –  Tommy 16.02.2011 в 19:24
Показать остальные комментарии
4

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

    
ответ дан KeithS 16.02.2011 в 19:04
источник
  • Если вы придерживаетесь вычислительной части ASM, да. Что C не может сделать, так это то, что делает остальная часть ASM: настройка состояния машины (попробуйте загрузить ESP на X86 с чистого C), настроить аппаратное обеспечение (устройства, уровни прерываний, управление памятью) и фактические операции ввода-вывода устройства, управлять задачами (переключение контекста, прерывания). Так что C - низкий уровень, но Паскаль не сильно отличается. C не голый металл. –  Ira Baxter 16.02.2011 в 19:08
  • ... при условии, что они знают язык ассемблера для целевой платформы, над которой они работают. –  FrustratedWithFormsDesigner 16.02.2011 в 19:09
  • C не может выполнять хвостовую рекурсию. См. C минус минус –  user606723 16.02.2011 в 19:11
  • Нет. Хороший программист на C знает, как писать хороший код C и, при необходимости, писать переносимый C. Там действительно не нужно, чтобы хороший программист C был очень хорош или даже хорош на любом языке ассемблера. Это требует знания не C, а внутренности вашего компилятора, чтобы угадать, как он скомпилирует любой не очень-очень простой фрагмент кода. –  eq- 16.02.2011 в 19:13
  • @ user606723: Конечно, может. Ничто в стандарте не запрещает это, и если оптимизация хвоста хвоста была одной из самых ранних «оптимизаций» оптимизирующего компилятора. –  eq- 16.02.2011 в 19:16
3

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

    
ответ дан Mr Coder 16.02.2011 в 19:06
источник
2

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

ответ дан Kevin Sylvestre 16.02.2011 в 19:03
источник
  • Расширения языка C могут поддерживать «сборку смешивания». –  eq- 16.02.2011 в 19:07
  • @eq Хорошая точка, обновленная. –  Kevin Sylvestre 16.02.2011 в 19:10
  • Я имею доступ только к проекту C99, но ключевое слово «asm» определено в J.5.10 с «Ключевое слово asm может использоваться для вставки языка ассемблера непосредственно в вывод транслятора (6.8). Наиболее распространенная реализация через инструкцию формы: asm (character-string-literal); ". Поэтому просто поддержка сборки не является технически расширением; как вы поддерживаете сборку. –  Tommy 16.02.2011 в 19:21
  • @ Tommy. Обратите внимание, что раздел J.5 называется «общим расширением». Это не обязательные функции. Он доступен почти в каждом компиляторе C, но технически он все еще является расширением компилятора. –  bta 16.02.2011 в 19:26
  • @bta стало ясно, что я плохой читатель. Пожалуйста, обработайте мои комментарии так, как будто они были удалены (но это не так, с тех пор не будет понятно, о чем вы говорите в ответ) –  Tommy 16.02.2011 в 19:35
2

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

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

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

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

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

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

Считалось, что

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

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

ответ дан peoro 16.02.2011 в 19:14
источник
  • То, что я подразумеваю под низким уровнем, - это то, что каждый означает, когда говорят, что C - это язык низкого уровня. Если бы я знал, что мне не нужно будет задавать вопрос. –  ecounysis 16.02.2011 в 19:23
  • @ecounysis: я хочу сказать, что стандартного определения для низкого уровня нет. Если вы хотите сгенерировать определенную последовательность команд сборки, C не сможет этого сделать. Если вы хотите реализовать реальный мир, то алгоритм C будет идеальным. –  peoro 16.02.2011 в 19:26
  • (@who_downvoted: не могли бы вы объяснить, пожалуйста?) –  peoro 16.02.2011 в 19:27
  • +1 для встречного голосования, так как этот ответ совершенно прекрасен –  vikingosegundo 16.02.2011 в 19:37
2

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

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

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

    
ответ дан nos 16.02.2011 в 19:09
источник
  • Но это верно, если вы пишете программу в сборе или даже машинный код, который работает в пользовательском пространстве современной ОС. Это не свойственно ни одному языку, на котором вы вручную управляете памятью. Для простых систем с плоской памятью и без понятия виртуальной памяти вы можете использовать C для прямого доступа к адресам памяти. –  cdcdcd 16.04.2018 в 12:01
1

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

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

    
ответ дан Tommy 16.02.2011 в 19:15
источник
1

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 используется и встроить его автоматически в вызывающую функцию, полностью исключив вызов подпрограммы.

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

    
ответ дан Will Hartung 16.02.2011 в 19:22
источник
1

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

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

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

Ссылка

Ссылка

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

    
ответ дан user606723 16.02.2011 в 19:26
источник
  • Что означает «близко к оборудованию»? Я думаю, это то, к чему я пытаюсь ответить на свой вопрос. Кроме того, как «близко к оборудованию» является C? –  ecounysis 16.02.2011 в 19:30
  • Из уст лошади: «[BCPL, B и C]« близки к машине »тем, что абстракции, которые они вводят, легко заземляются в конкретных типах данных и операциях, предоставляемых обычными компьютерами, и они полагаются на библиотеку подпрограмм для ввода-вывода и других взаимодействий с операционной системой ». - от cm.bell-labs.com/cm/cs/who/dmr/chist.html. Например, int in C тесно связан с родным словом на базовой платформе и, следовательно, имеет аналогичные ограничения по диапазону и точности. Сравните с таким языком, как Haskell, где числовые типы могут иметь произвольную точность. –  John Bode 16.02.2011 в 20:00
  • @John Bode Спасибо. Это очень полезно. –  ecounysis 16.02.2011 в 20:31
0

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

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

register int foo asm ("a5");
    
ответ дан Daniel Earwicker 16.02.2011 в 19:13
источник
  • За спецификацию (проект) C99: «Объявление идентификатора для объекта с регистром спецификатора класса хранения предполагает, что доступ к объекту должен быть как можно быстрее. Степень, в которой такие предложения эффективны, определяется реализацией ». GCC расширения, я думаю, основная проблема будет в том, где вы хотели бы получить доступ к регистру специального назначения, который не отображается на тип C? Регистр статуса является общим и очевидным, но не очень полезным; у вашего оборудования могут быть другие. –  Tommy 16.02.2011 в 19:18
-1

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

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

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

    
ответ дан user606723 16.02.2011 в 19:11
источник
  • Вы правы. Вот почему я задал вопрос. –  ecounysis 16.02.2011 в 19:21
  • Мою мыслью, что вам, вероятно, нужно немного побольше прочитать, прежде чем задавать такой вопрос ... Это то, о чем можно было бы написать книгу ... –  user606723 16.02.2011 в 19:23
  • Я постоянно читаю книги, и я никогда не видел ответа на этот вопрос. –  ecounysis 16.02.2011 в 19:34
  • вот почему я больше не задаю вопросы о stackoverflow. Люди не заботятся о том, чтобы помочь вам или ответить на ваш вопрос, они просто хотят решить более сложные проблемы для очков. Что-то еще, кроме этого, и они говорят, что вы мочитесь и читаете книгу –  OzzyTheGiant 10.01.2017 в 23:03