views:

914

answers:

10

Hi,

I want to know, why is it too hard to make a program run in many OSes, like Windows and Linux, without including glue code. They all share the same architecture (x86), so I think it should be simple. Furthermore, C is standardized, so why are implementations diferent in these OSes? Why is it hard to follow the standard and implement a universal library for all OSes?

I have programmed in C for almost two years, and currently I use glib for portability.

I'm not looking for a solution to this problem, I'm already using glib for this purpose. But I want to know why it is necessary, why it's dificult to make a C library without differences.

[ADD]

For example, when i write a program in C/Glib, i use the gchar/gint and so on types indeed the C primitive types, in wikipedia about glib, it says that :

"Features

On an elementary level GLib provides type definitions replacing the C primitive types char, int, float, and so on in order to improve portability"

Why C primitive types is not portable and the whole language?

Thanks for all the answers.

+17  A: 

Making your basic C program that computes a little and prints results work is easy.

The problem is that any C program that does anything substantial is going to rely on a lot of services from the operating system, and those differ in many ways. File I/O tends to be similar, but when it comes to graphics, they differ a lot. And that is the crux of the problem.

Matthias Wandel
Even file I/O, which the C standard library provides functions for, is a mess. Trying to do file I/O and permissions _securely_ is a pain at best, and impossible in many situations.Consider that all of the C file I/O functions require a filename for identification. This can cause (innocuous-looking) race conditions where you check for a file's existence then open one of the same name I/O. See https://www.securecoding.cert.org/confluence/display/seccode/09.+Input+Output+%28FIO%29 for more :)
Andrew Keeton
yes; underlying processor architecture is abstracted well by the C language (apart from some accumulator-width dependent types). It is the OS which you really need, and which is poorly supported by the standard libraries. In fact: you can even consider Glib or Qt as glue code, only you don't need to write it yourself.
Adriaan
+14  A: 

It is not hard if you stick to the core standard (the examples in K&R will generally run with minimal correction). But the core standard does not support many things that people would like to do. Little things like:

  • rooting around in the file system
  • more sophisticated IO than plain streamed text
  • asking the OS for access to clocks and printers and networks
  • talking to other processes


Concerning the portability of the primitive types: the standard specifies minimum size limits for these types, but does not specify actual sizes. Most platforms support sizes that are larger than the minimums, but not all platforms have the same larger sizes. So glib and other cross-platform projects define their own type so that they only need one set of #ifdef switches to get the sizes right.

dmckee
A: 

I think it's because every compiler has a tension between being standard and portable on one hand and using optimal, OS-proprietary features on the other.

I think ANSI C code is quite portable, as long as you write to the standard. Your code is portable to the degree that GNU and Microsoft are both sticking to the standard.

duffymo
+4  A: 

Anything that your C program interacts with is going to be a dependency. If those dependencies are the exact same across every C implementation on all the systems, then you're in luck, your program is portable.

The basic file I/O operations are this way.

But if there is even one difference in the way your code is implemented on a system, it's not portable to that system anymore.

So, if your code doesn't touch anything, it's portable.

I think the main idea here is to maximize portability, so that you can minimize what you have to change to port to a new system.

Carson Myers
+1  A: 

The code is portable, but thats not the problem.

The problem is that most larger applications use libraries which are part of the OS. So for example if you write a network app it might use the built in UPNP library for windows, and the Bonjour library on OS X, and some other zero-conf service on other unix flavors.

Another example would could a simple notepad application. It might use the native save-file dialogues for the OS it is running on. A different version would need to be compiled for each OS to bind to the save-file dialogue library for that OS.

I hope these examples are clear enough :)

Nippysaurus
+10  A: 
Norman Ramsey
+1  A: 

For java/ruby/... somebody ported the VM and your code just runs. This makes it easy as long as you a ok with the services provided by the VM. In C you have to do all the work for your self because you can directly interact with the hardware and OS. This adds dependencies but but gives you great power and flexibility. This is what makes C great but it can be a pain if you switch OS or hardware.

Gerhard
A: 

C does give more power compared to other higher level languages.

Different Processor (CISC and RISC based), 32 and 64bits does put the bit streams of data in different order. There are some supporting APIs to do the conversion, but not totally reliable for all cases.

Windows and Unix have custom flags which need to be used for building.

Sachin
+1  A: 

Obviously, some software requires OS specific features, but it's quite interesting to think what can be created in C without using such things:

  • A C or C++ compiler (though not all of the standard library)
  • An assembler for any assembly language
  • A linker for the above
  • An interpreter for a scripting language
  • Text processing tools like sed, grep etc.
  • A simple editor (anyone remember ed?)

In fact, all the basic development tools can be developed (and historically were developed) in C without using OS-specific features.

anon
+1  A: 

Why C primitive types is not portable and the whole language?

The primitive types are portable in that they're guaranteed to support a minimum range of values (e.g., the int type must at least support values in the range -32767 to 32767). They're not guaranteed to have the same size or alignment restrictions because different architectures have different requirements.

The C standard tries to strike a reasonable balance between portability, performance, and ease of implementation, meaning that there are compromises in all three areas. It's possible to write C programs that are useful and trivially portable, but that means limiting yourself to a command-line driven interface, simple file I/O, and making no assumptions about word size or alignment.

Remember that C is a product of the early '70s, when the dominant computing environment consisted of large, time-share systems accessed via dumb character-based terminals; processor time and memory were expensive, and it was rare for a data center to support more than one or two different platforms at a time, so performance was the bigger concern than byte-for-byte portability. Forty years later that's no longer the case, but there's also forty years of legacy code to support, so the language definition can't change too radically.

John Bode