简体   繁体   English

Windows上的C编译器之间有什么实际区别?

[英]What are the practical differences between C compilers on Windows?

A program written in Visual C/C++ 2005/2008 might not compile with another compiler such as GNU C/C++ or vice-versa. 用Visual C / C ++ 2005/2008编写的程序可能无法使用其他编译器(如GNU C / C ++)编译,反之亦然。 For example when trying to reuse code, which uses windows.h, written for a particular compiler with another, what are the differences to be aware of? 例如,当尝试重用使用windows.h的代码时,为另一个特定的编译器编写代码时,需要注意哪些差异?

Is there any information about how to produce code which is compatible with either one compiler or another eg with either GC/C++ or MSVC/C++? 是否有任何关于如何生成与一个编译器或另一个编译器兼容的代码的信息,例如GC / C ++或MSVC / C ++? What problems will attempting to do this cause? 这会导致什么问题?

What about other compilers, such as LCC and Digital Mars? 那么其他编译器呢,比如LCC和Digital Mars?

The first thing to do when trying to compile code written for MSVC to other compilers is to compile it with Microsoft-extensions switched off. 尝试将为MSVC编写的代码编译到其他编译器时,首先要做的是在关闭Microsoft扩展的情况下编译它。 (Use the /Za flag, I think). (我认为使用/ Za标志)。 That will smoke out lots of things which GCC and other compilers will complain about. 这将吸引大量GCC和其他编译器会抱怨的事情。

The next step is to make sure that Windows-specific APIs (MFC, Win32, etc.) are isolated in Windows-specific files, effectively partioning your code into "generic" and "windows-specific" modules. 下一步是确保Windows特定的API(MFC,Win32等)在Windows特定的文件中被隔离,从而有效地将您的代码分成“通用”和“特定于Windows”的模块。

Remember the argument that if you want your web page to work on different browsers, then you should write standards-compliant HTML? 请记住,如果您希望您的网页在不同的浏览器上运行,那么您应该编写符合标准的HTML吗?

Same goes for compilers. 编译器也是如此。

At the language level, if your code compiles without warnings on GCC with -std=c89 (or -std=c++98 for C++), -pedantic -Wall, plus -Wextra if you're feeling brave, and as long as you haven't used any of the more blatant GNU extensions permitted by -pedantic (which are hard to do accidentally) then it has a good chance of working on most C89 compilers. 在语言层面,如果您的代码在GCC上编译而没有警告,使用-std = c89(或-std = c ++ 98 for C ++),-pedantic -Wall,加上-Wextra,如果你感觉很勇敢,并且只要你还没有使用-pedantic允许的任何更明显的GNU扩展(这很难意外),那么它很有可能在大多数C89编译器上工作。 C++ is a bit less certain, as you're potentially relying on how complete the target compiler's support is for the standard. C ++有点不确定,因为您可能依赖于目标编译器对标准的支持程度。

Writing correct C89 is somewhat restrictive (no // comments, declarations must precede statements in a block, no inline keyword, no stdint.h and hence no 64bit types, etc), but it's not too bad once you get used to it. 编写正确的C89有点限制(没有//注释,声明必须在块中的语句之前,没有内联关键字,没有stdint.h,因此没有64位类型等),但是一旦习惯它就不会太糟糕。 If all you care about is GCC and MSVC, you can switch on some language features you know MSVC has. 如果你关心的只是GCC和MSVC,你可以打开一些你知道MSVC的语言功能。 Otherwise you can write little "language abstraction" headers of your own. 否则,您可以编写自己的“语言抽象”标题。 For instance, one which defines "inline" as "inline" on GCC and MSVC/C++, but "__inline" for MSVC/C. 例如,在GCC和MSVC / C ++上将“内联”定义为“内联”,但在MSVC / C中定义为“__inline”。 Or a MSVC stdint.h is easy enough to find or write. 或者MSVC stdint.h很容易找到或写入。

I've written portable code successfully in the past - I was working mostly on one platform for a particular product, using GCC. 我以前成功编写了可移植代码 - 我主要使用GCC在一个特定产品的平台上工作。 I also wrote code that was for use on all platforms, including Windows XP and Mobile. 我还编写了可在所有平台上使用的代码,包括Windows XP和Mobile。 I never compiled it for those platforms prior to running a "test build" on the build server, and I very rarely had any problems. 在构建服务器上运行“测试构建”之前,我从未为这些平台编译过它,而且我很少遇到任何问题。 I think I might have written bad code that triggered the 64bit compatibility warning once or twice. 我想我可能编写了错误的代码,触发了一次或两次64位兼容性警告。

The Windows programmers going the other way caused the occasional problem, mostly because their compiler was less pedantic than ours, so we saw warnings they didn't, rather than things that GCC didn't support at all. 另一方面,Windows程序员引起了偶尔的问题,主要是因为他们的编译器不像我们那样迂腐,所以我们看到他们没有警告,而不是GCC根本不支持的事情。 But fixing the warnings meant that when the code was later used on systems with more primitive compilers, it still worked. 但修复警告意味着当代码稍后在具有更原始编译器的系统上使用时,它仍然有用。

At the library level, it's much more difficult. 在图书馆一级,这要困难得多。 If you #include and use Windows APIs via windows.h, then obviously it's not going to work on linux, and the same if you use KDE with GCC and then try to compile with MSVC. 如果#include并通过windows.h使用Windows API,那么显然它不适用于linux,如果你使用KDE和GCC然后尝试使用MSVC进行编译也是如此。

Strictly speaking that's a platform issue, not a compiler issue, but it amounts to the same thing. 严格来说,这是一个平台问题,而不是编译器问题,但它是相同的事情。 If you want to write portable code, you need an OS abstraction API, like POSIX (or a subset thereof) that all your targets support, and you need to be thinking "portable" when you write it in the first place. 如果你想编写可移植代码,你需要一个OS抽象API,比如所有目标支持的POSIX(或其子集),并且当你首先编写它时,你需要考虑“可移植”。 Taking code which makes heavy use of windows-specific APIs, and trying to get it to work on GCC/linux, is basically a complete rewrite AFIAK. 使用大量使用特定于Windows的API的代码,并尝试使其在GCC / linux上运行,基本上是一个完整的重写AFIAK。 You might be better off with WINE than trying to re-compile it. 使用WINE可能比尝试重新编译它更好。

You're mixing up "compilers" and "OSs". 你正在混淆“编译器”和“操作系统”。 <windows.h> is not something that MSVC C compiler brings to the table: it's C-specific embodiment of Windows API. <windows.h>不是MSVC C编译器带给表的东西:它是Windows API的C特定实施例。 You can get it independently from Visual Studio. 您可以从Visual Studio中独立获取它。 Any other C compiler on Windows is likely to provide it. Windows上的任何其他C编译器都可能提供它。 On the Linux side, for example, you have <unistd.h>, <pthereads.h> and others. 例如,在Linux方面,您有<unistd.h>,<pthereads.h>等。 They are not an essential part of GCC, and any other compiler that compiles for Linux would provide them. 它们不是GCC的重要组成部分,任何其他编译Linux的编译器都会提供它们。

So you need to answer two different questions: how can I code C in such a way that any compiler accepts it? 所以你需要回答两个不同的问题:如何以任何编译器接受它的方式编写C? And how do I hide my dependencies on OS? 如何隐藏我对操作系统的依赖?

As you can tell from the diverse answers, this topic is fairly involved. 从各种答案可以看出,这个主题非常复杂。 Bearing that in mind here are some of the issues I faced when recently porting some code to target three platforms (msvc 8/Windows, gcc 4.2/Linux, gcc 3.4/embedded ARM9 processor). 记住这里我最近将一些代码移植到三个平台(msvc 8 / Windows,gcc 4.2 / Linux,gcc 3.4 /嵌入式ARM9处理器)时遇到的一些问题。 It was originally only compiling under Visual Studio 2005. 它最初只在Visual Studio 2005下编译。

a) Much code that's written on the Windows platforms uses types defined in windows.h. a)在Windows平台上编写的许多代码都使用在windows.h中定义的类型。 I've had to create a "windows_types.h" file with the following in it: 我必须创建一个“windows_types.h”文件,其中包含以下内容:

#ifndef _WIN32
    typedef short              INT16;
    typedef unsigned short     UINT16;
    typedef int                INT32;
    typedef unsigned int       UINT32;
    typedef unsigned char      UCHAR;
    typedef unsigned long long UINT64;
    typedef long long          INT64;
    typedef unsigned char      BYTE;
    typedef unsigned short     WORD;
    typedef unsigned long      DWORD;
    typedef void *             HANDLE;
    typedef long               LONG;
#endif

Ugly, but much easier than modifying the code that, previously, was only targeting Windows. 丑陋,但比修改以前只针对Windows的代码要容易得多。

b) The typename keyword was not required in templated code to declare types. b)模板化代码中不需要typename关键字来声明类型。 MSVC is lax in this regard (though I assume certain compiler switches would have generated a warning). MSVC在这方面是松懈的(虽然我假设某些编译器开关会产生警告)。 Had to add it in a number of places. 不得不在很多地方添加它。

c) Simple, but time-consuming: Windows is not case sensitive and many #included files were specified with incorrect case causing problems under Linux. c)简单但耗时:Windows不区分大小写,并且许多#included文件在Linux下指定了不正确的情况导致问题。

d) There was a fair chunk of code using the Windows API for many things. d)有很多代码使用Windows API来处理很多事情。 An example was for CRITICAL_SECTIONS and INTERLOCKED_INCREMENT. 一个例子是CRITICAL_SECTIONS和INTERLOCKED_INCREMENT。 We used the boost libraries as much as possible to replace these issues but reworking code is time-consuming. 我们尽可能地使用boost库来替换这些问题,但重新编写代码非常耗时。

e) A lot of the code relied on headers being included in precompiled headers. e)许多代码依赖于头文件包含在预编译头文件中。 We had issues with using pch on gcc3.4 so we had to ensure that all .h/cpp files correctly included all their dependencies (as they should have in the first place). 我们在gcc3.4上使用pch时遇到了问题,因此我们必须确保所有.h / cpp文件都正确地包含了所有依赖项(因为它们应该首先包含在内)。

f) VS 2005 has two nasty bugs. f)VS 2005有两个令人讨厌的错误。 auto_ptr's can be assigned to anything and temporary variables are allowed to be passed to reference parameters. auto_ptr可以分配给任何东西 ,允许临时变量传递给引用参数。 Both fail to compile (thankfully!) under gcc but rework is required. 两者都无法编译(谢天谢地!)在gcc下,但需要返工。

g) Bizarrely, we had template code that was trying to explicitly specialise class template functions. g)奇怪的是,我们有模板代码试图明确地专门化模板函数。 Not allowed. 不允许。 Again gcc refused, VS 2005 let it go. 再次gcc拒绝,VS 2005让它走了。 Easy enough to rework into regular overloads once the problem is understood. 一旦理解了问题,就足够容易重新定期进行超载。

h) Under VS 2005 std::exception is allowed to be constructed with a string. h)在VS 2005下,允许使用字符串构造std :: exception。 Not allowed under gcc or the standard. 不允许使用gcc或标准。 Rework your code to prefer to use one of the derived exception classes. 重新编写代码以优先使用其中一个派生的异常类。

Hopefully that's the kind of information you were looking for! 希望这是您正在寻找的那种信息!

Well this is a quite difficult question. 那么这是一个非常困难的问题。 Fact is that MSVC does not support the newest C standard, about it's c++ compliance I can tell you anyything. 事实上,MSVC不支持最新的C标准,关于它的c ++兼容性,我可以告诉你任何东西。 Howerver "windows" C is understand by both MSVC and gcc you just can not hope for the other way. 强大的“windows”C是MSVC和gcc所理解的,你不能指望其他方式。 Eg if you use ANSI C99 features then you might have a hard time "porting" from gcc to MSVC. 例如,如果您使用ANSI C99功能,那么您可能很难从gcc“移植”到MSVC。

But as long as you try the way MSVC-> gcc you chances will be better. 但只要你尝试MSVC-> gcc的方式,你的机会就会更好。 The only point you have to be aware of is the libraries. 您必须注意的唯一一点是库。 Most of the libraries on Windows are supposed to work with MSVC and so you need some extra tools to make them accessible to gcc also. Windows上的大多数库都应该与MSVC一起使用,因此您需要一些额外的工具来使它们也可以访问gcc。

LCC is a quite older system,which AFAIKT does not support much from ANSI C99, it also needs tools from MSVC to work properly. LCC是一个相当老的系统,AFAIKT不支持ANSI C99,它还需要MSVC的工具才能正常工作。 LCC is "just " a compiler. LCC“只是”一个编译器。

lcc-win32 is a C Development system striving to be ANSI C99 compliant. lcc-win32是一个致力于符合ANSI C99标准的C开发系统。 It comes along with linker, IDE etc. 它附带链接器,IDE等。

I can not tell about the state of Digital Mars implementation 我无法分辨数字火星实施的状态

Then there is also Pelles-C which is a fully fledged IDE also. 还有Pelles-C,它也是一个完全成熟的IDE。

And we have hanging around OpenWatcom. 我们在OpenWatcom附近闲逛。 Which once was quite a decent system but I can't tell how conformant it is. 曾经是一个相当不错的系统,但我不知道它是多么符合。

All in all the "best" you can hope for the easier way from MSVC -> other system but it will probably be much worse the other way round. 总而言之,你可以希望从MSVC更容易的方式 - >其他系统,但反过来可能会更糟糕。

Regards Friedrich 关心弗里德里希

A program written in Visual C/C++ 2005/2008 might not compile with another compiler such as GNU C/C++ or vice-versa. 用Visual C / C ++ 2005/2008编写的程序可能无法使用其他编译器(如GNU C / C ++)编译,反之亦然。

This is true if you either (1) use some sort of extension available in one compiler but not another (the C++ standard, for instance requires the typename and template keywords in a few places but many compilers -- including Visual C++ don't enforce this; gcc used to not enforce this either, but changed in 3.4 ) or (2) use some standard compliant behavior implemented on one compiler but not another (right now the poster boy for this is exported templates, but only one or two compilers support this, and Visual C++ and gcc are not in that group). 如果你要么(1)在一个编译器中使用某种扩展而不是另一个编译器(C ++标准,例如在一些地方需要typenametemplate关键字,但许多编译器 - 包括Visual C ++不强制执行这个; gcc过去也没有强制执行这个,但是在3.4 )或(2)中改变了使用在一个编译器上实现的一些标准兼容行为而不是另一个编译器(现在这个海报男孩是导出模板,但只有一个或两个编译器支持这个,而Visual C ++和gcc不在那个组中)。

For example when trying to reuse code, which uses windows.h, written for a particular compiler with another, 例如,当尝试重用使用windows.h的代码时,为另一个特定的编译器编写,

I've never seen a problem doing this. 我从来没有见过这样做的问题。 I have seen a problem using Microsoft's windows.h in gcc. 我在gcc中看到了使用Microsoft的windows.h的问题。 But when I use gcc's windows.h in gcc and Microsoft's windows.h in Visual C++ I have access to all of the documented functions. 但是当我在gcc中使用gcc的windows.h和在Visual C ++中使用Microsoft的windows.h时,我可以访问所有记录的函数。 That's the definitions of "implemented windows.h" after all. 毕竟这就是“实现的windows.h”的定义。

what are the differences to be aware of? 有什么区别需要注意?

The main one I've seen is people not knowing about the dependent template / typename thing mentioned above. 我见过的主要是人们不知道上面提到的依赖template / typename事物。 I find it funny that a number of people think gcc is not smart enough to do what Visual C++ does, when in reality gcc had the feature first and then decided to remove it in the name of standards compliance. 我觉得有趣的是,许多人认为gcc不够聪明,无法做到Visual C ++所做的事情,而实际上gcc首先拥有该功能,然后决定以符合标准的名义删除它。

In the near future you will run into problems using C++0x features. 在不久的将来,您将遇到使用C ++ 0x功能的问题。 But both gcc and Visual C++ have implemented the easier things in that standard. 但是gcc和Visual C ++都实现了该标准中更容易的东西。

vs2008 is a lot more standards compliant than 2005. vs2008比2005年更符合标准。
I have had more problems going the other way, especially the 'feature' of gcc that lets you allocate an array with a variable size at run time "int array[variable]" which is just pure evil. 我遇到了更多问题,尤其是gcc的'feature',它允许你在运行时分配一个可变大小的数组“int array [variable]”,这只是纯粹的邪恶。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM