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

Как написать переносимый код в С++?

Какие вещи я должен иметь в виду, чтобы написать переносимый код? Поскольку я начинаю С++, я хочу практиковать его с самого начала.

Спасибо.

4b9b3361

Ответ 1

  • научитесь использовать стандартную библиотеку
  • читать книги (например, этот)
  • когда вы опытны, научитесь использовать boost

Ответ 2

Сохраняйте код, специфичный для платформы, отдельно от кода многократного использования, предпочтительно в другом файле, но, по крайней мере, в другой функции. Если вы начнете с #if WIN32 и #if CYGWIN и #if BSD повсюду, у вас будет кошмар обслуживания.

Затем, скомпилируйте, по крайней мере, две разные платформы рано и часто. Типичными вариантами являются Visual С++ для Windows и gcc в Linux. Поскольку ни системные библиотеки, ни компилятор не используются совместно, вы поймаете непереносимый код, прежде чем он станет глубоко укоренившимся в вашем дизайне.

Ответ 3

Какие вещи я должен иметь в виду, чтобы написать переносимый код?

  • Храните несколько компиляторов рядом, регулярно проверяйте код на целевых платформах. Если вы используете кросс-платформенное программное обеспечение для windows windows/linux, держитесь вокруг mingw, visual studio express (т.е. "Microsoft compiler" ) и Linux-установки с g++ (или используйте виртуальную машину). Даже если ваш код совершенен, у компилятора может быть какая-то неожиданная причуда. Например, некоторые версии компилятора ms имеют ограничение на размеры строковых констант, которые gcc не имеет.
  • Не полагайтесь на размеры стандартных типов. Например, на msvc sizeof (wchar_t) - 2 байта. При установке Linux это может быть 4 байта. Используйте sizeof (если вам это нужно) или старайтесь не использовать размер любого типа в коде. И вы не должны предполагать, что указатель имеет размер 4 байта (передача указателя пользовательских данных в сценарий вызова api) - это будет 8 байтов на 64 бит.
  • Не используйте специальные правила, макросы и расширения для компилятора. Например, избегайте "#pragma once".
  • Не используйте расширения для стандартной библиотеки (предоставляемые разработчиком компилятора). Однако это более применимо к функциям библиотеки C. Например, MS-компилятор предоставляет несколько "безопасных" (например, strcpy_s) версий стандартных подпрограмм C-стиля. Что, конечно же, не будет доступно на других платформах.
  • Будьте очень осторожны, если вы решите использовать подпрограммы C-стиля (например, sprintf) в коде на С++. (Я знаю, что это должна быть плохая практика, но в некоторых случаях это полезно). У них несколько разные реализации, расширения и различное количество параметров. Например, sprintf может иметь разные дополнительные форматы, которые по-разному реализуются на разных платформах. Например, в прошлый раз, когда я проверил, что "% S" ведет себя по-разному в msvc и gcc в подпрограмме vswprintf.
  • Не полагайтесь на типы данных, специфичные для компилятора, такие как __int32. Весьма вероятно, что вам понадобится какой-то тип, который будет иметь длину 4 байта (или что-то в этом роде) - используйте typedef в сочетании с условной компиляцией ( "#ifdef WIN32" ). ИЛИ типы использования, предоставляемые кросс-платформенной библиотекой. Например, SDL предоставляет такие типы, как Uint8, Qt 4 имеет quint32 и т.д. Это довольно распространенная практика.
  • Избегайте прямых вызовов ОС. Используйте стандартные функции для доступа к файлам.
  • Когда вам нужно использовать вызовы, специфичные для ОС, используйте условную компиляцию (#ifdef WIN32 и т.д.)
  • Попробуйте использовать ту же систему сборки на всех платформах. В Linux нет MSBuild. Используйте gnumake, cmake, scons или qmake. Хотя в некоторых из этих систем вам придется кодировать флаги для разных компиляторов, везде можно будет использовать один и тот же script. Например, он отлично работает с SConstructs. И поддержание одного здания script для всех платформ может быть проще, чем синхронизация изменений в разных системах сборки.
  • Для всех операций, требующих взаимодействия с операционной системой (Gui, манипулирование файлами), используйте межплатформенные библиотеки. Qt - хороший выбор.

Ответ 4

Начните писать программы с командной строкой. Когда вы будете готовы, найдите кросс-платформенный инструментарий для окон, например Qt.

Если вам интересно писать многоязычный код, используйте стороннюю уникодную библиотеку, такую ​​как ICU, а не полагаться на платформу -специальные библиотеки.

Ответ 5

Используйте STL-типы, когда это возможно. Будьте осторожны с использованием зависимых от системы типов и API. Например, не используйте такие типы, как UINT и DWORD в Windows.

Вы можете использовать библиотеку, например boost, чтобы упростить запись переносного кода. Если вам нужен GUI, подумайте об использовании кросс-платформенного инструментария, такого как Qt.

Иногда вам нужно написать код конкретной платформы, и в этих случаях вы можете сделать что-то вроде этого:

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

Ответ 6

Другие говорили это раньше, но вот мой взгляд на это:

1) Вам нужен С++? Это не лучший язык для написания портативного кода, потому что он близок к голым металлам. Java, Python, Perl, PHP или Javascript могут быть лучше для вас.

2) Если вам нужен С++, не пытайтесь писать полностью переносимый код, это практически невозможно. Вместо этого заранее определите, на каких платформах вы хотите поддерживать. Например: Linux, MacOS X, Windows

3) Убедитесь, что вы постоянно проверяете свой код на всех выбранных платформах. Не просто строить на Windows и рассчитывать просто скомпилировать версию Linux "когда это будет сделано". Компиляция на всех платформах ежедневно и убедитесь, что вы продолжаете тестировать их на наличие проблем.

Ответ 7

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

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

Теперь вот основные категории, которые я могу придумать с головы.

Расширения компилятора

Как, например, использование массивов переменных:

void func(int const n)
{
  int array[n];
}

Это не стандарт, но многие компиляторы поддерживают его, тем не менее, потому что это просто практично.

Расширения стандартных библиотек

Многие стандартные реализации библиотек предоставляют std::hash_map, которые никогда не указывались. Если вы используете его в своем коде, он не переносится.

Современная тенденция состоит в том, чтобы спрятать этот материал в пространство имен std::tr1, чтобы программисты знали, что это расширение.

Также имейте в виду, что многие определяют typedef или макросы, которые не являются общими (например PRETTY_FUNCTION). Стандартный не указан макросом, и очень мало typedef.

Специфично для платформы

Например, размер и выравнивание int или double не указаны в стандарте. Если вы делаете бит-twiddling и ожидаете, что он будет иметь 32 бита, вы будете ввернуты на 64-битные платформы даже без изменения вашего компилятора.

API платформы

Наши программы предназначены для компиляции, и они часто предназначены для взаимодействия с компьютером, на котором они запускаются:

  • для доступа к аппаратным средствам
  • для доступа к файловой системе
  • для доступа к экрану

Вам нужно найти кросс-платформенные портативные API-интерфейсы или сворачивать свои собственные. Проверьте некоторые библиотеки в приведенном ниже списке.

Библиотеки

Большинство хорошо написанных библиотек в значительной степени переносимы, просто убедитесь, что они поддерживают:

  • компиляторы, которые вас интересуют
  • интересующие вас платформы

Хорошие библиотеки включают:

  • Apache (коллекция библиотек)
  • Повышение
  • Qt (для графики)
  • ICU (для обработки Юникода)

Остальные вам нужно просмотреть... и это требует времени.

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

Для платформы вы должны начать с Windows и одного Linux-вкуса. Для компиляторов выберите любые два (с Комо, если вы можете себе это позволить).

Ответ 8

Некоторые рекомендации:

  • Держите бизнес-конец кода и отдельный графический интерфейс.
  • Избегайте использования специфичных для компилятора костылей (#pragma и т.д.)
  • Используйте обычные выражения, которые не изменят поведение с компилятором/платформой, а не с помощью трюков с малым количеством бит.
  • Если он касается аппаратного обеспечения, он принадлежит драйверу устройства.
  • Используйте заголовки типов данных типа types.h(uint32_t и т.д.).
  • Используйте уровень абстракции операционной системы, чтобы вы не вызывали непосредственно вызовы операционной системы.

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

Не все коды должны быть написаны таким образом. Если вы разрабатываете свое приложение очень модульным способом с четко определенными границами ответственности, то 90-95% кода может быть переносимым без боли. Затем просто выделите 5-10% в очень локализованной области, которая должна быть настроена для новой платформы.

Ответ 9

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

Получите справочник, независимый от платформы. Stroustrup Язык программирования С++ - прекрасная ссылка, хотя это не хорошая книга для начинающих, чтобы попытаться учиться. Не полагайтесь на ссылки для данной реализации. Например, MSDN полезен, но основное внимание уделяется тому, как писать программы Windows с использованием Visual С++, а не как писать программы, которые будут компилироваться и выполняться где угодно.

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

Ответ 10

Независимый от ОС код на удивление трудно сделать на С++. Рассмотрим этот тривиальный пример:

#include <iostream>
int main(int argc, char** argv) {
  std::cout << argv[0] << std::endl;
}

Это совершенно допустимый С++, но он не переносимый, потому что он не будет принимать аргументы командной строки Unicode в Windows. Правильная версия для Windows:

#include <iostream>
int wmain(int argc, wchar_t** argv) {
  std::wcout << argv[0] << std::endl;
}

Конечно, это опять-таки непереносимо, работая только на Windows и нестандартно. Таким образом, вы даже не можете написать переносимую функцию main() в С++, не прибегая к условной компиляции.

Ответ 11

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

Ответ 12

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

проблема в том, что Windows не совсем совместима с POSIX, но есть библиотеки, которые реализуют определенные функции POSIX, такие как: [1]: http://sourceware.org/pthreads-win32/