[Zlib-devel] #elif is not portable on pre-ANSI compilers

Cosmin Truta cosmin at cs.toronto.edu
Wed Apr 16 14:53:01 EDT 2003


Hi,

I noticed that crc32.c contains #elif directives, which are not
supported on pre-ANSI compilers. The guard "#ifdef __STDC__" can assure
the inclusion of <limits.h>, but it cannot prevent the preprocessor from
dying with an "unknown directive" message.

Of course #elif's can be replaced with more convoluted #else...\n#if...,
but I wonder if the use of unsigned short is really necessary. My
understanding is that the code works if u4 holds _at_least_ 32 bits, and
not only if it holds _exactly_ 32 bits. The only potentially problematic
piece of code is the following:

  #ifdef BYFOUR
      {
          u4 endian;

          endian = 1;
          if (*((unsigned char *)(&endian)))
              return crc32_little(crc, buf, len);
          else
              return crc32_big(crc, buf, len);
      }
  #else /* !BYFOUR */

I think, however, that this works correctly even if u4 is bigger than 4
bytes.

If my assumption is correct, then you don't need to check for unsigned
short, because C guarantees that int is never narrower than short.
On the other hand, the use of short instead of int may incur performace
penalties, at least on some machines.

Another thing that I wish to point out is that 4294967295 can cause
problems (at least warnings) on 16-bit platforms; 4294967295UL is safe.
But shouldn't it be 0xffffffffUL instead? The rest of the code uses it
in hex form, so for the sake of consistency (and readability, because
0xffffffffUL is more obvious than 4294967295UL), shouldn't this one be
the same?

Cosmin


*** crc32.c~    Wed Apr 02 23:29:56 2003
--- crc32.c     Wed Apr 16 15:50:00 2003
***************
*** 28,41 ****
  #  ifdef __STDC__       /* need ANSI C limits.h to determine sizes */
  #    include <limits.h>
  #    define BYFOUR
! #    if (UINT_MAX == 4294967295)
         typedef unsigned int u4;
- #    elif (ULONG_MAX == 4294967295)
-        typedef unsigned long u4;
- #    elif (USHRT_MAX == 4294967295)
-        typedef unsigned short u4;
  #    else
! #      undef BYFOUR     /* can't find a four-byte integer type! */
  #    endif
  #  endif /* __STDC__ */
  #endif /* !NOBYFOUR */
--- 28,43 ----
  #  ifdef __STDC__       /* need ANSI C limits.h to determine sizes */
  #    include <limits.h>
  #    define BYFOUR
! #    if (UINT_MAX >= 0xffffffffUL)
         typedef unsigned int u4;
  #    else
! #      if (ULONG_MAX >= 0xffffffffUL)
!          typedef unsigned long u4;
! #      else
!          /* It's unlikely that unsigned long is smaller than 4 bytes,
!             but we consider this possibility anyway. */
! #        undef BYFOUR     /* can't find a four-byte integer type! */
! #      endif
  #    endif
  #  endif /* __STDC__ */
  #endif /* !NOBYFOUR */





More information about the Zlib-devel mailing list