简体   繁体   English

C程序在Windows和Unix OS上跨平台差异

[英]C program cross platform differences on Windows and Unix OS

Is there any difference in C that is written in Windows and Unix? 用Windows和Unix编写的C有什么区别吗?
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. 我教C和C ++,但我的一些学生回来说,一些示例程序不能在Unix中运行它们。 Unix is alien to me. Unix对我来说很陌生。 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. 如果有任何差异,那么我应该建议我们的部门投资Unix系统,因为目前我们实验室中没有Unix系统。 I do not want my students to feel that they have been denied or kept away from something. 我不希望我的学生觉得他们被拒绝或远离某些东西。

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. 当您不遵守裸C标准时,通常会出现这种问题,并对可能不正确的环境做出假设。 These may include reliance on: 这些可能包括依赖:

  • nonstandard, platform specific includes ( <conio.h> , <windows.h> , <unistd.h> , ...); 非标准,特定平台包括( <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 invoke fflush 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); 未定义的行为( fflush(stdin) ,正如其他人所报告的那样,不需要按标准做任何事情 - 它实际上是未定义的行为来调用fflush除输出流之外的任何东西;通常,较旧的编译器对违反某些微妙规则更宽容如严格别名,所以要小心“聪明”指针技巧);
  • data type size (the short =16 bit, int = long =32 bit assumption doesn't hold everywhere - 64 bit Linux, for example, has 64 bit long ); 数据类型大小( short = 16位, int = long = 32位假设并不适用于所有地方 - 例如,64位Linux有64位long );
  • in particular, pointer size ( void * isn't always 32 bit, and can't be always casted safely to an unsigned long ); 特别是指针大小( void *并不总是32位,并且不能总是安全地转换为unsigned 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 particular size_t , ptrdiff_t , uintptr_t ) 一般来说,你应该注意涉及指针的转换和比较,你应该总是使用提供的类型来代替“普通” int (特别参见size_tptrdiff_tuintptr_t
  • data type "inner format" (the standard does not say that float s and double s are in IEEE 754, although I've never seen platforms doing it differently); 数据类型“内部格式”(标准并没有说float s和double s在IEEE 754中,虽然我从未见过平台做不同的事情);
  • nonstandard functions ( __beginthread , MS safe strings functions; on the other side, POSIX/GNU extensions) 非标准函数( __beginthread ,MS安全字符串函数;另一方面,POSIX / GNU扩展)
  • 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); 编译器扩展( __inline__declspec#pragma s,...)以及通常以双下划线开头的任何内容(或者在旧的非标准实现中使用单个下划线);
  • console escape codes (this usually is a problem when you try to run Unix code on Windows); 控制台转义码(当你尝试在Windows上运行Unix代码时,这通常是个问题);
  • 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; 回车格式:在正常的字符串是\\n随处可见,但在写入文件时,它\\n对* NIX, \\r\\n在Windows上, \\r上预OSX的Mac电脑; 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. 转换是由文件流自动处理的,因此在您真正想要写二进制数据时要小心打开二进制文件,并在想要写文本时将它们保留为文本模式。

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 C and (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相媲美),你只需选择一个。

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. 但是,如果您正在教C(而不是系统编程),您应该能够轻松编写可移植代码。 The fact that you are not doing so makes me wonder about the quality of your training materials. 你没有这样做的事实让我想知道你的培训材料的质量。

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. 随MSVC一起提供的标准库以及与典型Linux或Unix编译器一起提供的标准库不同,您可能会遇到兼容性问题。 There may also be minor dialectic variations between MSVC and GCC. 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. 在类似unix的环境中测试示例的最简单方法是在现有的Windows工具包上安装Cygwin或MSYS。 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. 它们基于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. Cygwin是最“unix like”,基于cygwin.dll ,它是一个仿真层,在本机Win32 API之上模拟unix系统调用。 Generally anything that would compile on Cygwin is very likely to compile on Linux, as Cygwin is based on gcc and glibc. 通常,在Cygwin上编译的任何内容都很可能在Linux上编译,因为Cygwin基于gcc和glibc。 However, native Win32 APIs are not available to applications compiled on Cygwin. 但是,在Cygwin上编译的应用程序无法使用本机Win32 API。

  • MSYS/MinGW32 is designed for producing native Win32 apps using GCC. MSYS / MinGW32旨在使用GCC生成原生Win32应用程序。 However, most of the standard GNU and other OSS libraries are available, so it behaves more like a unix environment than VC does. 但是,大多数标准GNU和其他OSS库都可用,因此它的行为更像是unix环境而不是VC。 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. 实际上,如果您正在处理不使用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. 虽然在您的实验室中安装Linux可能是一件有用的事情(如果您无法获得新服务器的资金,请使用VMWare播放器或其他一些虚拟机管理程序),您可以使用上述任一工具链来获取可能“关闭”的内容足够'为你的目的。 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. 你可以学习unix作为你的想法,Cygwin和MSYS都会给你一个类似unix的环境,在此期间可以给你一些温和的介绍。

C syntax must be the same if both Windows and Unix compilers adhere to the same C standard. 如果Windows和Unix编译器都遵循相同的C标准,则C语法必须相同。 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. 我被告知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。

There is this thing called Ansi C . 这个叫做Ansi C的东西。 As long as you code purely Ansi C, there should be no difference. 只要您编写纯粹的Ansi C代码,就没有区别。 However, this is a rather academic assumption. 然而,这是一个相当学术的假设。

In real life, I have never encountered any of my codes being portable from Linux to Windows and vice versa without any modification. 在现实生活中,我从未遇到任何代码可以从Linux移植到Windows,反之亦然,没有任何修改。 Actually, this modification S (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. 实际上,这个修改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编译器......

在Windows或* nix下,C编程语言之间应该没有区别,因为语言是由ISO标准指定的。

The C language itself is the portable from Windows to Unix. C语言本身是从Windows到Unix的可移植版本。 But operating system details are different and sometimes those intrude into your code. 但操作系统的详细信息不同,有时会侵入您的代码。

For instance Unix systems typically use only "\\n" to separate lines in a text file, while most Windows tools expect to see "\\r\\n". 例如,Unix系统通常只使用“\\ n”来分隔文本文件中的行,而大多数Windows工具都希望看到“\\ 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. 有一些方法可以解决这种差异,让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,并在与学生共享之前使用它来测试代码。

I think its critical that you familiarize yourself with unix right now. 我认为你现在熟悉unix是至关重要的。

An excellent way to do this is a with a Knoppix CD. 一个很好的方法是使用Knoppix CD。

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. 尝试使用gc在Linux下编译程序,当它们不起作用时,跟踪问题(#include <windows>?)并使其工作。 Then return to windows, and it'll likely compile ok. 然后返回到窗口,它可能编译好了。

In this way, you will discover your programs become cleaner and better teaching material, even for lab exercises on windows machines. 通过这种方式,您将发现您的程序变得更清洁,更好的教学材料,甚至是在Windows机器上进行实验练习。

A common problem is that fflush(stdin) doesn't work on Unix. 一个常见的问题是fflush(stdin)在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): 解决方案是使用这样的(未经测试):

do
{
    int c = getchar();
}
while (c != '\n' && c != EOF);

Similarly, you need to avoid anything that causes undefined behavior. 同样,您需要避免任何导致未定义行为的事情。

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

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