writing portable C (DOS to UNIX) -- suggestions? 
Author Message
 writing portable C (DOS to UNIX) -- suggestions?

Quote:

>I'd like to anticipate any problems that could arise when porting [C]
>to UNIX.

A good starting point is to decide on the flavor of the language;  ANSI
C is best because it's a standard to which a lot of vendors adhere
(but, you have the problem that some vendors -- like Sun -- ship a K&R
compiler unless you cough-up some bucks).  If you choose ANSI C, get a
copy of the standard (you can get it for about $50 from ANSI in New
York, New York) and stick to the library functions that are described
in there.  Use the standard as your reference manual (it's pretty easy
to understand) rather than your compiler's library reference manual.

Now that you've got a good start, there's a bunch of little niggleys
that'll get you (listed in no particular order).  I'll try to name as
many as come to mind.  Many of them will have to do with addressing
memory.

        - Don't assume that memory exists outside of where it is allocated.
          The only two addresses that are legal to reference (but not
          DEreference) that are not within the scope of something that
          has been allocated (through any means including off the
          stack, from the global space, or through dynamic allocation)
          are 0 (NULL) and the address one beyond an array (don't
          assume that dereferencing either is okay, but having a
          pointer point to that address is cool).  Some processors can
          bomb even when you load the address, so the following might
          bomb on some machines (even though the math looks right):

                pointer = (&array[0] - 100) + 100;

          Another place where one might abuse addressing is in count-down
          loops (trying to get tricky):

                for (ptr=&array[SIZE-1]; ptr >= array; --ptr)
                        /* could cause a boom when 'ptr' < 'array' */

        - Don't use the comma operator to join expressions of unlike type.

        - Don't use bit fields.  Bit fields are, in general,
          non-portable (not because they're inherently that way, but
          because many compilers have gotten this wrong -- this may not
          be that big a deal since the ANSI standard and compliance
          issues have come into the compiler business).

        - Don't depend on the results of applying bitwise operators to
          signed (specifically negative) integers or any floating point
          type.  In general, depending on machine representation is a
          bad idea.  This can include depending on byte ordering,
          floating point representation, or even (though this isn't as
          big a problem as the others) two's complement notation.

        - Watch type promotion when adding integers to pointers (always
          put the pointer first).  For example:

                ptr1 = ptr2 + intValue; /* is okay */
                ptr1 = intValue + ptr2; /* is often not calculated properly */

        - Watch your pointer punning (dealing with pointers to different
          types).  For example:

                char    *ptr1;
                int             *ptr2;

                /* ... */

                ptr2 = ptr1;    /* bad idea */

          The problem is that, on some processors, different types need
          different alignments in memory.  Assigning a pointer to a
          pointer to a bigger type incurs the possibility that the
          smaller pointer is improperly aligned to be a pointer to the
          bigger type.  If you need to do something like this, you can
          use a union to make the data transfer.

        - DON'T EVEN THINK OF DEREFERNCING A NULL POINTER.  This implys
          checking all pointers before you dereference them (for
          example, on entry to a function, check all the pointer
          arguments against NULL).

        - Don't depend on the sizes of types.  Use 'sizeof' and, if you
          need a 16-bit type, use 'typedef' surrounded by #ifdef's (in
          conjuction with #define MACHINE DOS, or whatever).

Hope this helps.

--
Wade Guthrie                     | Trying to program on MS-DOS is like trying

Me be not speaking for the Rock. |



Sun, 24 Mar 1996 23:24:43 GMT  
 writing portable C (DOS to UNIX) -- suggestions?

Quote:


>>I'd like to anticipate any problems that could arise when porting [C]
>>to UNIX.

[... A lot of good, sound advice truncated for brevity...]

Quote:
>If you choose ANSI C, get a
>copy of the standard (you can get it for about $50 from ANSI in New

  The FAQ says it costs four times this. :-)

Quote:
>Use the standard as your reference manual (it's pretty easy
>to understand) rather than your compiler's library reference manual.

        As a reference manual, yes, the ANSI standard is the final word.
But to learn portable programming, it is IMO better to go through the ANSI
rationale.  It is available via anonymous ftp (I forgot the site).

[...]

Quote:
>    - Don't use the comma operator to join expressions of unlike type.

        You mean as a matter of style?  Then I won't argue.  But syntactically
and semantically, there is nothing wrong in using the comma operator to join
expressions of unlike type. Are there any non-conforming compilers which
make a comma expression return a type different from the type of the last
expression?

Quote:
>    - Don't use bit fields.  Bit fields are, in general,
>      non-portable (not because they're inherently that way, but
>      because many compilers have gotten this wrong -- this may not
>      be that big a deal since the ANSI standard and compliance
>      issues have come into the compiler business).

        Bit fields _are inherently non-portable_.  The order of assignment of
the bits are implementation-defined (even in the ANSI standard).  The spacing
between consecutive bit fields is implementation defined (actually, the ANSI
standard says that the bit fields should be packed together if they fit into a
storage unit, but the type of the storage unit itself is
implementation-defined).

        Some other issues of portability that have come up on the net:

        There are a lot of reserved (or quasi-reserved) identifiers in
ANSI C. Section 7.13 (ISO version) gives a good list.  Also avoid all
identifiers beginning with an '_'.

         Be careful with variable arguments (use stdarg.h).  Don't treat a
va_list object as a char**, or in fact, as anything other than as a parameter
to a function call, or with the va_... macros.

        Do declare main() as int main(void) or as int main(int argc,
char **argv) or as something similar; don't go for void main(void) to shut off
warnings.

        For the sake of so-called efficiency, don't assume non-portable
things such as the number of bits in a char (the only guarantee available is
that it is greater than or equal to 8).

        Do not assume that all implementations would provide some compiler
flag to turn off structure padding. Lots of networking code typically declare
protocol headers as structures.  As long as structure padding can be turned
off, this works, else it fails.

        There should be plenty more to add to this do's and dont's list.

------
/* I prefer silver speech to golden silence. */

/* Ajoy Krishnan T,
   Software Engineer, Hughes Software Systems,
   New Delhi - 19, India.




Tue, 26 Mar 1996 01:27:00 GMT  
 writing portable C (DOS to UNIX) -- suggestions?

Quote:
>[... A lot of good, sound advice truncated for brevity...]

Thanks!

Quote:
>>If you choose ANSI C, get a
>>copy of the standard (you can get it for about $50 from ANSI in New
>  The FAQ says it costs four times this. :-)

The prices may have gone up, but I got my copy from ANSI for $50 plus
shipping (it worked out to something like $66).  At the time I got
mine, one could get it from Global Engineering Documents for about
$85.

Quote:
>to learn portable programming, it is IMO better to go through the ANSI
>rationale.  It is available via anonymous ftp (I forgot the site).

Yes!  I forgot to mention that.  The rationale comes with the standard
as well!  The standard also gives lists of implementation-defined
behavior that can help one understand the world of portable code.

Quote:
>there is nothing wrong in using the comma operator to join
>expressions of unlike type.

Some compilers do strange things in this case.  This may have improved
somewhat now that the ANSI standard is around.  I will still stay away
from it on the off-chance that 'Ernies ANSI C compiler' was upgraded
from his not-so-great K&R C compiler.

Quote:
>    For the sake of so-called efficiency, don't assume non-portable
>things such as the number of bits in a char (the only guarantee available is
>that it is greater than or equal to 8).

Good advice; in fact, don't assume anything about the size of variables.

--
Wade Guthrie                     | Trying to program on MS-DOS is like trying

Me be not speaking for the Rock. |



Tue, 26 Mar 1996 04:05:40 GMT  
 writing portable C (DOS to UNIX) -- suggestions?
Writing in ANSI / POSIX C/C++ is an ecellent idea.  While porting code
for AT&T (and myself at times) I have discovered that all hardware
companies have extensively investigated the portability issue.  Most will
supply Docs on the subject at little or no cost.


Tue, 26 Mar 1996 20:30:25 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. How can I create a portable (Unix, DOS) NULL-stream/-file that I can write to using fprintf in standard C?

2. Newbie: separate big .cs file into small .cs files

3. A portable way to remove globals on UNIX

4. Book suggestion for C and Unix

5. Portable code versus unix specific build procedures

6. portable UNIX programs

7. Need Suggestions for Porting some DOS C code to VC++

8. 32 bit DOS compiler suggestions

9. How to write portable(ish) C programs?

10. Tips for writing *truly* portable C?

11. Tips for writing *truly* portable C?

12. How to write a high portable C program ?

 

 
Powered by phpBB® Forum Software