Почему трудно писать переносные программы на C?

Я хочу знать, почему слишком сложно заставить программу запускаться во многих ОС, таких как Windows и Linux, без включения кода клея. Все они имеют одну и ту же архитектуру (x86), поэтому я считаю, что она должна быть простой. Кроме того, C стандартизирован, поэтому почему реализации в разных ОС? Почему трудно следовать стандарту и внедрять универсальную библиотеку для всех ОС?

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

Я не ищу решение этой проблемы, я уже использую glib для этой цели. Но я хочу знать, почему это необходимо, почему это делает невозможным создание библиотеки C без различий.

[ADD]

Например, когда я пишу программу в C/Glib, я использую gchar/gint и т.д. типы действительно примитивных типов C, в wikipedia о glib, он говорит, что:

"Особенности

На элементарном уровне GLib предоставляет определения типов, заменяющие примитивные типы C char, int, float и т.д., чтобы улучшить переносимость"

Почему примитивные типы C не переносятся и весь язык?

Спасибо за все ответы.

Ответы

Ответ 1

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

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

Ответ 2

Почему примитивные типы C не переносятся и весь язык?

В момент создания C было сочтено наиболее важным, чтобы int использовал размер естественного слова (или размер полуслова) целевой машины (которая в те дни могла быть 18 или 36 бит на PDP-10!) и менее важно, чтобы количество бит в int было легко предсказуемым, не говоря уже о том же на всех аппаратных средствах. Эффективность имела первостепенное значение, и особенно важно, чтобы в программе не было слишком много инструкций, чтобы ее можно было упаковать в маленькие воспоминания дня. Никто не хотел бы, например, моделировать 32-разрядную арифметику на 16-разрядной машине, которая может утроить количество инструкций, необходимых для выполнения арифметики, что делает невозможным размещение больших программ в памяти.

Почему трудно реализовать универсальную библиотеку?

Это не сложно. Проблема не в том, что нет универсальной библиотеки; проблема в том, что люди не могут согласиться с тем, что составляет универсальную библиотеку. (См.: GTK, KDE, QT, AT & T U/WIN + AST и т.д. Ad nauseam.) Но внедрение хорошей библиотеки очень сложно. Почему это сложно: дизайн библиотеки - это просто сложная проблема, и разумные люди могут и не согласны с тем, что представляет собой хороший дизайн. Таким образом, несколько проектов расширяются, а переносимость идет на доске.

Ситуация усугубляется очень тонкой стандартной библиотекой, которая поставляется с C. Но не будем забывать, что библиотека была разработана в те времена, когда программисту повезло получить 64 КБ для кода и еще 64 КБ для данных. К тому времени, когда пришли С++, они могли позволить себе стандартизировать на огромном раздутом свирепе, как в стандартной библиотеке шаблонов. Но когда была создана библиотека C, все должно было быть небольшим. Теперь, когда стандартная библиотека C неадекватна на сегодняшний день более амбициозным приложениям, слишком поздно для всех программистов на C согласовать один стандарт.


Совать профессора, получить лекцию...

Ответ 3

Это не сложно, если вы придерживаетесь основного стандарта (примеры в K & R обычно выполняются с минимальной коррекцией). Но основной стандарт не поддерживает многие вещи, которые люди хотели бы сделать. Маленькие вещи вроде:

  • поддержка файловой системы
  • более сложный IO, чем простой потоковый текст
  • запрос ОС на доступ к часам и принтерам и сетям
  • общение с другими процессами

Что касается переносимости примитивных типов:, стандарт определяет минимальные ограничения размера для этих типов, но не определяет фактические размеры. Большинство платформ поддерживают размеры, превышающие минимальные, но не все платформы имеют одинаковые размеры. Таким образом, glib и другие кросс-платформенные проекты определяют свой собственный тип, так что им нужен только один набор переключателей #ifdef для правильного выбора размеров.

Ответ 4

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

Основные операции ввода-вывода файла таковы.

Но если есть хоть одна разница в том, как ваш код реализован в системе, он больше не переносится в эту систему.

Итак, если ваш код ничего не трогает, он переносится.

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

Ответ 5

Код переносимый, но это не проблема.

Проблема заключается в том, что большинство более крупных приложений используют библиотеки, которые являются частью ОС. Например, если вы пишете сетевое приложение, оно может использовать встроенную библиотеку UPNP для окон и библиотеку Bonjour на OS X, а также некоторую другую службу с нулевым конфигом на других вариантах unix.

Еще один пример мог бы быть простым приложением для блокнота. Он может использовать собственные диалоги сохранения файлов для ОС, на которых он запущен. Для каждой ОС необходимо скомпилировать другую версию для привязки к библиотеке диалога сохранения файлов для этой ОС.

Я надеюсь, что эти примеры достаточно ясны:)

Ответ 6

Для java/ruby ​​/... кто-то портировал виртуальную машину, и ваш код просто запускался. Это упрощает работу, если вы согласны с услугами, предоставляемыми виртуальной машиной. В C вы должны выполнять всю работу для себя, потому что можете напрямую взаимодействовать с оборудованием и ОС. Это добавляет зависимости, но дает вам большую мощность и гибкость. Это то, что делает C отличным, но может быть больно, если вы переключаете ОС или аппаратное обеспечение.

Ответ 7

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

  • Компилятор C или С++ (хотя и не вся стандартная библиотека)
  • Ассемблер для любого языка ассемблера
  • Линкером для вышеперечисленного
  • Интерпретатор для языка сценариев
  • Инструменты обработки текста, такие как sed, grep и т.д.
  • Простой редактор (кто-нибудь помнит?)

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

Ответ 8

Почему примитивные типы C не переносятся и весь язык?

Примитивные типы переносимы, поскольку они гарантируют поддержку минимального диапазона значений (например, тип int должен, по крайней мере, поддерживать значения в диапазоне от -32767 до 32767). У них не гарантируется наличие ограничений по размеру или выравниванию, поскольку разные архитектуры имеют разные требования.

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

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

Ответ 9

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

Я думаю, что код ANSI C довольно портативен, если вы пишете стандарт. Ваш код переносится в зависимости от того, что GNU и Microsoft придерживаются стандарта.

Ответ 10

C дает больше мощности по сравнению с другими языками более высокого уровня.

Различные процессоры (CISC и RISC-based), 32 и 64 бит, помещают битовые потоки данных в другом порядке. Существуют некоторые поддерживающие API для преобразования, но не полностью надежные для всех случаев.

У Windows и Unix есть собственные флаги, которые необходимо использовать для создания.