Windows 和 Unix OS 上的 C 程序跨平台差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2295056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C program cross platform differences on Windows and Unix OS
提问by zapping
Is there any difference in C that is written in Windows and Unix?
I teach C as well as C++ but some of my students have come back saying some of the sample programs do not run for them in Unix. Unix is alien to me. Unfortunately no experience with it whatsoever. All I know is to spell it. If there are any differences then I should be advising our department to invest on systems for Unix as currently there are no Unix systems in our lab. I do not want my students to feel that they have been denied or kept away from something.
用 Windows 和 Unix 编写的 C 有什么区别吗?
我教 C 和 C++,但我的一些学生回来说,有些示例程序在 Unix 上不适合他们。Unix 对我来说很陌生。不幸的是没有任何经验。我所知道的就是拼写它。如果有任何差异,那么我应该建议我们的部门投资 Unix 系统,因为目前我们实验室中没有 Unix 系统。我不希望我的学生觉得他们被拒绝或远离某事。
回答by Matteo Italia
That kind of problems usually appear when you don't stick to the bare C standard, and make assumptions about the environment that may not be true. These may include reliance on:
当您不坚持裸 C 标准并对环境做出可能不正确的假设时,通常会出现这种问题。这些可能包括依赖:
- nonstandard, platform specific includes (
<conio.h>
,<windows.h>
,<unistd.h>
, ...); - undefined behavior (
fflush(stdin)
, as someone else reported, is not required to do anything by the standard - it's actually undefined behavior to invokefflush
on anything but output streams; in general, older compilers were more lenient about violation of some subtle rules such as strict aliasing, so be careful with "clever" pointer tricks); - data type size (the
short
=16 bit,int
=long
=32 bit assumption doesn't hold everywhere - 64 bit Linux, for example, has 64 bitlong
); - in particular, pointer size (
void *
isn't always 32 bit, and can't be always casted safely to anunsigned long
); in general you should be careful with conversions and comparisons that involve pointers, and you should always use the provided types for that kind of tasks instead of "normal"int
s (see in particularsize_t
,ptrdiff_t
,uintptr_t
) - data type "inner format" (the standard does not say that
float
s anddouble
s are in IEEE 754, although I've never seen platforms doing it differently); - nonstandard functions (
__beginthread
, MS safe strings functions; on the other side, POSIX/GNU extensions) - compiler extensions (
__inline
,__declspec
,#pragma
s, ...) and in general anything that begins with double underscore (or even with a single underscore, in old, nonstandard implementations); - console escape codes (this usually is a problem when you try to run Unix code on Windows);
- carriage return format: in normal strings it's
\n
everywhere, but when written on file it's\n
on *NIX,\r\n
on Windows,\r
on pre-OSX Macs; the conversion is handled automagically by the file streams, so be careful to open files in binary when you actually want to write binary data, and leave them in text mode when you want to write text.
- 非标准,特定于平台的包括 (
<conio.h>
,<windows.h>
,<unistd.h>
, ...); - 未定义的行为 (
fflush(stdin)
,正如其他人所报告的那样,标准不需要做任何事情——fflush
在输出流之外的任何东西上调用实际上都是未定义的行为;一般来说,旧的编译器对违反一些微妙的规则更宽容,比如严格的别名,所以要小心“聪明”的指针技巧); - 数据类型大小(
short
=16 位,int
==long
32 位假设并不适用于任何地方 - 例如,64 位 Linux 有 64 位long
); - 特别是,指针大小(
void *
并不总是 32 位,并且不能总是安全地转换为 anunsigned long
);一般来说,您应该小心涉及指针的转换和比较,并且您应该始终将提供的类型用于此类任务,而不是“普通”int
(特别参见size_t
,ptrdiff_t
,uintptr_t
) - 数据类型“内部格式”(标准没有说
float
s 和double
s 在 IEEE 754 中,尽管我从未见过平台以不同的方式这样做); - 非标准函数(
__beginthread
,MS 安全字符串函数;另一方面,POSIX/GNU 扩展) - 编译器扩展 (
__inline
,__declspec
,#pragma
s, ...) 以及通常以双下划线开头的任何内容(甚至在旧的非标准实现中以单下划线开头); - 控制台转义码(当您尝试在 Windows 上运行 Unix 代码时,这通常是一个问题);
- 回车格式:在普通字符串中,它
\n
无处不在,但当写入文件时,它\n
在 *NIX、\r\n
Windows、\r
OSX 之前的 Mac 上;转换是由文件流自动处理的,所以当你真正想写二进制数据时要小心地打开二进制文件,当你想写文本时将它们保留在文本模式。
Anyhow an example of program that do not compile on *NIX would be helpful, we could give you preciser suggestions.
无论如何,不能在 *NIX 上编译的程序示例会有所帮助,我们可以为您提供更准确的建议。
The details on the program am yet to get. The students were from our previous batch. Have asked for it. turbo C is what is being used currently.
该计划的详细信息尚未获得。学生是我们上一批的。已经要求了。turbo C 是目前正在使用的。
As said in the comment, please drop Turbo Cand (if you use it) Turbo C++, nowadays they are both pieces of history and have many incompatibilities with the current C and C++ standards (and if I remember well they both generate 16-bit executables, that won't even run on 64 bit OSes on x86_64).
正如评论中所说,请放弃 Turbo C和(如果你使用它)Turbo C++,现在它们都是历史的一部分,并且与当前的 C 和 C++ 标准有很多不兼容(如果我没记错的话,它们都生成 16 位可执行文件,甚至不能在 x86_64 上的 64 位操作系统上运行)。
There are a lot of free, working and standard-compliant alternatives (VC++ Express, MinGW, Pelles C, CygWin on Windows, and gcc/g++ is the de-facto standard on Linux, rivaled by clang), you just have to pick one.
有很多免费的、工作的和符合标准的替代方案(Windows 上的 VC++ Express、MinGW、Pelles C、CygWin,而 gcc/g++ 是 Linux 上的事实上的标准,可与 clang 相媲美),你只需要选择一个.
回答by zapping
The language is the same, but the libraries used to get anything platform-specific done are different. But if you are teaching C (and not systems programming) you should easily be able to write portable code. The fact that you are not doing so makes me wonder about the quality of your training materials.
语言是相同的,但是用于完成特定于平台的任何事情的库是不同的。但是,如果您正在教授 C(而不是系统编程),您应该能够轻松编写可移植代码。你没有这样做的事实让我怀疑你的培训材料的质量。
回答by ConcernedOfTunbridgeWells
The standard libraries that ship with MSVC and those that ship with a typical Linux or Unix compiler are different enough that you are likely to encounter compatibility issues. There may also be minor dialectic variations between MSVC and GCC.
MSVC 附带的标准库与典型 Linux 或 Unix 编译器附带的标准库大不相同,您很可能会遇到兼容性问题。MSVC 和 GCC 之间也可能存在细微的辩证差异。
The simplest way to test your examples in a unix-like environment would be to install Cygwin or MSYS on your existing Windows kit. These are based on GCC and common open-source libraries and will behave much more like the C compiler environment on a unix or linux system.
在类 Unix 环境中测试示例的最简单方法是在现有的 Windows 工具包上安装 Cygwin 或 MSYS。它们基于 GCC 和常见的开源库,其行为更像 unix 或 linux 系统上的 C 编译器环境。
Cygwin is the most 'unix like', and is based on a
cygwin.dll
, which is an emulation layer that emulates unix system calls on top of the native Win32 API. Generally anything that would compile on Cygwin is very likely to compile on Linux, as Cygwin is based on gcc and glibc. However, native Win32 APIs are not available to applications compiled on Cygwin.MSYS/MinGW32 is designed for producing native Win32 apps using GCC. However, most of the standard GNU and other OSS libraries are available, so it behaves more like a unix environment than VC does. In fact, if you are working with code that doesn't use Win32 or unix specific APIs it will probably port between MinGW32 and Linux more easily than it would between MinGW32 and MSVC.
Cygwin 是最像 unix 的,并且基于
cygwin.dll
,它是一个模拟层,在本机 Win32 API 之上模拟 unix 系统调用。一般来说,任何可以在 Cygwin 上编译的东西都很有可能在 Linux 上编译,因为 Cygwin 基于 gcc 和 glibc。但是,本机 Win32 API 不适用于在 Cygwin 上编译的应用程序。MSYS/MinGW32 专为使用 GCC 生成本机 Win32 应用程序而设计。但是,大多数标准 GNU 和其他 OSS 库都可用,因此与 VC 相比,它的行为更像是 Unix 环境。事实上,如果您正在使用不使用 Win32 或 unix 特定 API 的代码,它可能会比在 MinGW32 和 MSVC 之间更容易地在 MinGW32 和 Linux 之间移植。
While getting Linux installed in your lab is probably a useful thing to do (Use VMWare player or some other hypervisor if you can't get funding for new servers) you can use either of the above toolchains to get something that will probably be 'close enough' for your purposes. You can learn unix as takes your fancy, and both Cygwin and MSYS will give you a unix-like environment that could give you a bit of a gentle intro in the meantime.
虽然在您的实验室中安装 Linux 可能是一件有用的事情(如果您无法为新服务器获得资金,请使用 VMWare 播放器或其他虚拟机管理程序)您可以使用上述任一工具链来获得可能“关闭”的东西足以满足您的目的。您可以随心所欲地学习 Unix,Cygwin 和 MSYS 都将为您提供一个类 Unix 环境,同时可以为您提供一些温和的介绍。
回答by S.Tayefeh
There is this thing called Ansi C. As long as you code purely Ansi C, there should be no difference. However, this is a rather academic assumption.
有个东西叫Ansi C。只要您编写纯 Ansi C 代码,就应该没有区别。然而,这是一个相当学术的假设。
In real life, I have never encountered any of my codes being portable from Linux to Windows and vice versa without any modification. Actually, this modificationS(definitely plural) turned out into a vast amout of pre-processor directives, such as #ifdef WINDOWS ... #endif
and #ifdef UNIX ... #endif
... even more, if some parallel libs, such as OPENMPI were used.
在现实生活中,我从未遇到过我的任何代码无需任何修改即可从 Linux 移植到 Windows,反之亦然。实际上,这种修改S(绝对是复数)变成了大量的预处理器指令,例如#ifdef WINDOWS ... #endif
和#ifdef UNIX ... #endif
...甚至更多,如果使用一些并行库,例如 OPENMPI。
As you may imagine, this is totally contrary to readable and debugable code, but that was what worked ;-)
正如您可能想象的那样,这与可读和可调试的代码完全相反,但这就是有效的 ;-)
Besides, you have got to consider things already mentioned: UTF-8 will sometimes knock out linux compilers...
此外,您必须考虑已经提到的事情:UTF-8 有时会淘汰 linux 编译器......
回答by qrdl
C syntax must be the same if both Windows and Unix compilers adhere to the same C standard. I was told that MS compilers still don't support C99 in full, although Unix compilers are up to speed, so it seems C89 is a lowest common denominator.
如果 Windows 和 Unix 编译器都遵循相同的 C 标准,则 C 语法必须相同。有人告诉我 MS 编译器仍然不完全支持 C99,尽管 Unix 编译器已经达到了速度,所以 C89 似乎是一个最小的公分母。
However in Unix world you typically will use POSIX syscalls to do system stuff, like IPC etc. Windows isn't POSIX system so it has different API for it.
但是在 Unix 世界中,您通常会使用 POSIX 系统调用来执行系统调用,例如 IPC 等。Windows 不是 POSIX 系统,因此它具有不同的 API。
回答by John Knoeller
The C language itself is the portable from Windows to Unix. But operating system details are different and sometimes those intrude into your code.
C 语言本身是从 Windows 到 Unix 的可移植语言。但是操作系统细节是不同的,有时这些细节会侵入你的代码。
For instance Unix systems typically use only "\n" to separate lines in a text file, while most Windows tools expect to see "\r\n". There are ways to deal with this sort of difference in a way that gets the C runtime to handle it for you but if you aren't careful you know about them, it's pretty easy to write OS specific C code.
例如,Unix 系统通常只使用“\n”来分隔文本文件中的行,而大多数 Windows 工具都希望看到“\r\n”。有一些方法可以通过让 C 运行时为您处理这种差异的方式来处理这种差异,但是如果您不小心就会了解它们,那么编写操作系统特定的 C 代码非常容易。
I could that you run a Unix in a Virtual Machine and use that to test your code before you share it with your students.
我可以让您在虚拟机中运行 Unix 并使用它来测试您的代码,然后再与您的学生共享。
回答by Will
I think its critical that you familiarize yourself with unix right now.
我认为您现在熟悉 unix 至关重要。
An excellent way to do this is a with a KnoppixCD.
一个很好的方法是使用KnoppixCD。
Try to compile your programs under Linux using gc, and when they don't work, track down the problems (#include <windows>?) and make it work. Then return to windows, and it'll likely compile ok.
尝试在 Linux 下使用 gc 编译您的程序,当它们不工作时,找出问题(#include <windows>?)并使其工作。然后返回到 Windows,它可能会编译正常。
In this way, you will discover your programs become cleaner and better teaching material, even for lab exercises on windows machines.
通过这种方式,您会发现您的程序变得更清晰、更好的教材,即使是在 windows 机器上的实验室练习。
回答by Jichao
There should be no difference between the C programming language under windows or *nix,cause the language is specified by the ISO standard.
windows下和*nix下的C编程语言应该没有区别,因为语言是ISO标准规定的。
回答by Bastien Léonard
A common problem is that fflush(stdin)
doesn't work on Unix.
Which is perfectly normal, since the standard doesn't define how the implementation should handle it.
The solution is to use something like this (untested):
一个常见的问题是它fflush(stdin)
在 Unix 上不起作用。这是完全正常的,因为标准没有定义实现应该如何处理它。解决方案是使用这样的东西(未经测试):
do
{
int c = getchar();
}
while (c != '\n' && c != EOF);
Similarly, you need to avoid anything that causes undefined behavior.
同样,您需要避免任何导致未定义行为的事情。