Перевод с Visual C++ на gcc
(правила программирования программ на C++, которые должны компилироваться и под Visual Studio и под GCC)
GCC (GNU Compiler Collection) - это очень известный компилятор многих языков программирования, в том числе и языка С++. А популярен он главным образом по 2-м причинам а) Он бесплатен б) Он способен компилировать под множество платформ (Windows, Linux, MacOSX, SymbianOS и т.д.). Хотя большинство программистов (особенно на начальном этапе) пользуются компилятором Microsoft Visual Studio (ввиду удобства интерфейса и отладчика), многие из них вскоре сталкиваются с проблемой портирования своей программы под другие платформы, а тут, увы, без GCC не обойтись. Зачастую возникает проблема - написанный под Visual Studio код не хочет компилироваться под GCC.
Эта статья будет интересна людям, которые хотят, чтобы их код компилировался не только компилятором Microsoft Visual C++, но и GCC. Даже если вы планируете заняться сменой компилятора или портированием под другие платформы лишь в далеком будущем - прочитайте статью. Возможно, вы запомните некоторые рекомендации и сэкономите себе потом капельку времени. Считайте это просто сборником советов в примерах.
#pragma once
1) #pragma once - есть изобретение компании Microsoft(как и все диретивы начинающиеся с #pragma ). Напомню, что ставится эта директива в начале файла и говорит компилятору о том, чтобы он не подключал текущий файл больше одного раза.В GCC это не сработает, поэтому нужно писать по старинке:
#ifndef _MY_MODULE_
#define _MY_MODULE_ // это пишем в начале файла
// код нашего модуля/файла
#endif // это пишем в конце файла
Работа с типами
2) GCC не знает таких типов как size_t и void*. Чтобы они появились нужно подключить файлы <stdio.h> или <stddef.h>, то же касается нулевого указателя NULL.3) GCC (особенно под линуксом) строго относится к конвертации указателей разных типов.
Visual Studio на такую запись выдаст предупреждение, а gcc наверняка выдаст ошибку:
Код работает только в Visual Studio | Код работает в Visual Studio и gcc |
unsigned char * a; char * b = a; |
unsigned char * a; char * b = (char*)a; |
Работа с шаблонами
4) GCC строго относится к шаблонам. Так выглядит запись в студии:Код работает только в Visual Studio | Код работает в Visual Studio и gcc |
template { void do() { //... wchar_t * wcharBuff = (wchar_t *)allocateArray(10); //... } }; |
template { void do() { //... wchar_t * wcharBuff = (wchar_t *)Shared //... } }; |
10) При объявлении шаблонов необходимо ставить пробел между std::vector<T, SharedStdContainerAllocator<T>@Тут должен быть пробел@>. Рассмотрим это на примере:
Код работает только в Visual Studio | Код работает в gcc |
template <class T> class Vector : public std::vector<T, SharedStdContainerAllocator<T>> {} | template <class T> class Vector : public std::vector<T, SharedStdContainerAllocator<T> > {} |
Макросы
5) В больших макросах не пишите так(поставленные вместе "->" и "##" вызовут ошибку компиляции):Код работает только в Visual Studio | Код работает в Visual Studio и gcc |
#define _WRITE_LOG(str, module, level) \ if (log) \ { \ log->##level (str, module); \ } |
#define _WRITE_LOG(str, module, level) \ if (log) \ { \ log->level (str, module); \ } |
6) Если вы использовали многострочные макросы, разделённые символом '\'(как в предыдущем примере), и при компиляции получили множество странных ошибок - первым делом проверьте наличие лишних пробелов после символа '\' в конце каждой строки. Их там быть не должно.
7) Старайтесь в конце каждого файла ставить один символ окончания строки.
Это соответствует стандарту, а gcc очень строго следует стандарту. Иначе на каждый файл вы рискуете, получить примерно такое предупреждение:
In file included from
C:\Work\String\import\Modules.h:38,
from
C:\Work\String\src\Main.cpp:8:
C:\Work\String\Global.h:344:30:
warning: no newline at end of file
Причем с каждым следующим файлом к его сообщению будут плюсоваться такие же сообщения касательно предыдущих файлов. То есть будет огромное количество бесполезных предупреждений. Попробуйте потом в этой каше найти сообщение об ошибке.
Другой вариант - если вам сложно/лень следить за этим, просто добавьте опцию -w во время компиляции. Она выключит показ предупреждений во время компиляции. Но увлекаться этим не следует.
Линковка
8) В Visual C++ есть очень удобная вещь. Директива:#pragma comment(lib, "имя_библиотеки.lib")
Она говорит компилятору, чтобы он во время линковки подключил указанную библиотеку. Замечательная штука, но в GCC такой нет.
Все библиотеки в GCC нужно подключать прописывая их в командной строке компилятора. Пример:
g++ -o TestExe.exe *.o -Llib -lm -ldl -w "Библиотека3.a" " Библиотека2.a" "Библиотека1.a"
(Заметьте, что в GCC библиотеки имеют расширение .а, а не .lib)
"Библиотека3.a" " Библиотека2.a" "Библиотека1.a" - имена подключаемых библиотек.
Очень важен порядок в котором они подключаются: последними идут самые базовые и независимые от других файлы.
Ассемблерные вставки
9) Ассемблерные вставки: мало того что в GCC они выгладят иначе, так ещё они имеют другой синтаксис. Учитывайте это в будущем. Пример:Код работает только в Visual Studio | Код работает в gcc |
_asm { mov eax,1 mov ebx,0ffh int 80h } |
__asm__ __volatile__( "movl $1,%eax\n\t" "movl $0xff,%ebx\n\t" "int $0x80\n\t" ) |
Подробнее о синтакисисе и различиях ассемблерных команд можно почитать здесь:
http://asm.sourceforge.net//articles/linasm.html
При полном или частичном копировании необходимо указывать ссылку на данную статью.
Юрий (Дата )
Все вопросы и предложения высылайте на адрес soft_support@list.ru. Необходимо в заголовке указать название статьи.
Оставь свой отзыв
floke e-mail: floke@mail.ruДата: 23.04.11 |