Path: utzoo!attcan!uunet!ingr!jones From: jones@ingr.UUCP (Mark Jones) Newsgroups: comp.lang.c Subject: Re: How do a write portable programs? Summary: Don't use NULL, use ZERO Message-ID: <2515@ingr.UUCP> Date: 8 Sep 88 14:08:19 GMT References: <1056@nmtsun.nmt.edu> Organization: Intergraph Corp. Huntsville, Al Lines: 72 In article <1056@nmtsun.nmt.edu>, warner@hydrovax.nmt.edu (M. Warner Losh) writes: > write portable 'C' code. Things like don't use 0, use NULL, but be > sure to always cast it. Instead of using NULL, use ZERO, and don't worry about casting it. In K & R (first edition) page 192 the following statement is made regarding assignment operators. "... it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer distinguishable from a pointer to any object." (For a very close look at this subject, get sept/oct issue of "The C Users Journal" (published by CUG) pages 29-36. > How do I write program that are easily protable when I HAVE TO use the > system calls (be they setitimer() or lib$init_timer() or int21()...). Is > there a good and easy way that I can write my programs so that most of the > code never has to be touched when I port? What is the best way of handling > system dependent routines? Assume the whole world is UNIX and then write > UNIX system call emulation on those that aren't? Or should I write > routines that will do some functions (say turn off echo, but that is a bad > example) regardless of how that function gets done. Should I use zillions > of #ifdefs everywhere? or should there be files that contain source code > for only one system? > If at all possible, stick to std K & R functions (if they are not in the K & R book (first edition), don't use them. If that isn't possible, try to find a function in the ANSI C spec that will do what you want. If there still isn't one, write your own, and in that function, place your #ifdefs to handle different OS, here is where you would place lib$init_timer() and int21 calls. Keep the main body of your code clear of anything system dependent. Do not rely on the size of anything. If there is a need for a 32-bit number, do it like this: #if sizeof(int) == 4 typedef bit32 int /* pick your own name here */ #else #if sizeof(long) == 4 typedef bit32 long #endif #endif Watch out for sign extension, If you plan to assign a character to an int, declare it an unsigned if you want it to still be a character when it gets there. For example: { char c = 0x85; int i; /* assuming 32 bit ints */ i = c; /* i = 0xffffff85 */ } or { unsigned char c = 0x85 int i; i = c; /* i = 0x00000085 */ } For the next few years, try to stay with K & R, and don't use ANSI extensions, this is because not everyone has the ANSI extensions. For examples, if you use prototypes (and you should), place them in a header file and put #ifdefs around them. > More files are easier to read, but harder to maintain, etc) Try to keep things broken into several files, based on functionality, the small amount of overhead in maintaining the program is worth it when it comes to getting it running on a foreign target, also, if the communications facilities for porting the source are poor, it can save some real headaches. Mark Jones