Почему трудно писать переносимые программы на Си? - PullRequest
15 голосов
/ 11 августа 2009

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

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

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

[ADD]

1008

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

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

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

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

Ответы [ 10 ]

26 голосов
/ 11 августа 2009

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

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

19 голосов
/ 11 августа 2009

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

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

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

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

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


Ткните профессора, прочитайте лекцию ...

15 голосов
/ 11 августа 2009

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

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

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

7 голосов
/ 11 августа 2009

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

Основные операции ввода-вывода файлов выполняются следующим образом.

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

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

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

3 голосов
/ 11 августа 2009

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

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

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

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

1 голос
/ 11 августа 2009

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

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

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

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

1 голос
/ 11 августа 2009

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

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

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

1 голос
/ 11 августа 2009

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

0 голосов
/ 11 августа 2009

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

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

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

0 голосов
/ 11 августа 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...