Статьи / Перевод с Visual C++ на gcc

Перевод с Visual C++ на gcc


Отправить ссылку:

Перевод программы с 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 class Base : public Shared
{
  void do()
  {
    //...
    wchar_t * wcharBuff = (wchar_t *)allocateArray(10);
    //...
  }
};
template class Base : public Shared
{
  void do()
  {
    //...
    wchar_t * wcharBuff = (wchar_t *)Shared::allocateArray(10);
    //...
  }
};

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