From 3497910673432783836
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,738ae3371beb3408
X-Google-Attributes: gidf78e5,public
From: AllanW <allan_w@my-deja.com>
Subject: Re: portable method of determining endianness byte order.
Date: 1999/11/23
Message-ID: <81cpkd$t5e$1@nnrp1.deja.com>
X-Deja-AN: 551884260
X-NNTP-Posting-Host: 205.231.129.3
Approved: stephen.clamage@sun.com (comp.std.c++)
References: <38329967.470B6CED@hqs.mid.gmeds.com> <814kpp$j6j@library1.airnews.net>
X-Snookums: I love you
X-UID: 0000000001
X-Status: $$$T
X-Http-User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)
X-Http-Proxy: 1.0 PROXY, 1.0 x40.deja.com:80 (Squid/1.1.22) for client 205.231.129.3
Organization: Deja.com - Before you buy.
X-Article-Creation-Date: Tue Nov 23 01:11:45 1999 GMT
X-MyDeja-Info: XMYDJUIDallan_w
Newsgroups: comp.std.c++
Originator: clamage@taumet


In article <814kpp$j6j@library1.airnews.net>,
  "Bill Wade" <bill.wade@stoner.com> wrote:
>
>
> Pukalo Boyd 810-492-3661 wrote in message
> <38329967.470B6CED@hqs.mid.gmeds.com>...
> >I have been trying to find a portable method of determining the
> >endianness byte order at compile time
> >to produce code that will work properly on both windows and unix
> >machines. I have searched the documentation
> >i have ( the books on the C Standard Library and the C++ Standard
> >Library) and havent found anything. Please help. Any pointers or
> >suggestions would be very helpful. Thanks.
>
> There is no standard way.  In many cases tests like
>   (('abcd' & 0xff) == 'd')
> can be used to successfully distinguish endianness at compile time.

Presumably you mean to use this in preprocessor directives:

    #if (('abcd' & 0xFF) == 'd')
      // ...
    #endif

However, this won't work. First off, many systems don't
handle multiple-character char literals like 'abcd'.
Second, there is no requirement that the host compiler
and the target system have the same endianness. To say
that another way, there is no requirement that the
preprocessor and the compiler treat this expression the
same way.

To do this you must use one of two different techniques:

    * Have at least one header file that has specific versions
      for each OS and compiler that you use. Part of copying
      over the source code to the next compiler would involve
      creating this header file which is used throughout the
      system. For instance, when copying the files to a system
      which will use the Microsoft compiler, you would also
      copy file ENVIRON_WINDOWS_MICROSOFT.H to ENVIRON.H.
      However, if you were porting it to a unix box with GCC
      then you would instead copy file ENVIRON_UNIX_GCC.H to
      ENVIRON.H.

      In the ENVIRON_WINDOWS_MICROSOFT.H file, you would have:
          // Microsoft C or C++ running on Intel platform
          const int LOWESTBYTE =0;
          const int LOWERBYTE  =1;
          const int HIGHERBYTE =2;
          const int HIGHESTBYTE=3;
          // Four-byte signed integer type
          typedef long INT4;
          // ... etc ...
      Other systems would have identical statements except that
      the values might be different.

    * Another way is to have just one file named ENVIRON.H,
      but with specific sections for each compiler. This
      relies on knowledge of compiler-specific pre-defined
      symbols. For instance, all versions of Microsoft C or
      C++ have defined the symbol __MSVC__, so you could
      have a section like this:
          #ifdef __MSVC__
          // Microsoft C or C++ running on Intel platform
          const int LOWESTBYTE =0;
          const int LOWERBYTE  =1;
          const int HIGHERBYTE =2;
          const int HIGHESTBYTE=3;
          // Four-byte signed integer type
          typedef long INT4;
          // ... etc ...
          #endif

      You would have one section like this for each compiler
      that you support; you may have to dig through the
      documentation to find some pre-defined symbol (or
      combination of symbols) for each compiler. If neccesary,
      you could change the build commands to add additional
      symbols; all compilers that I know of have a command-
      line switch such as /DXXX to define symbol XXX. You
      could use this to define a symbol on one platform, if
      you couldn't find any helpful symbols created by the
      compiler.

With each of these techniques, it's advisable to add an
assert in main() to make sure that it's set correctly.
Since the assert will only be tested once, the run-time
penalty is approximately zero:

    void assert_endian() {
        union {
            char c[sizeof(INT4)];
            INT4 l;
        } u;
        u.l = 0x01020304;
        if (    sizeof(INT4) != 4    ||
            u.c[LOWESTBYTE]  != 0x04 ||
            u.c[LOWERBYTE]   != 0x03 ||
            u.c[HIGHERBYTE]  != 0x02 ||
            u.c[HIGHESTBYTE] != 0x01)
        {
            // The assert will trigger if asserts are enabled
            assert(0); // Endian order set wrong!

            // Asserts aren't enabled,
            // but don't let program run!
            exit(4);
        }
    }

    int main() {
        // We only need to call this once
        assert_endian();

        // ... whatever else...
    }

--
Allan_W@my-deja.com is a "Spam Magnet," never read.
Please reply in newsgroups only, sorry.


Sent via Deja.com http://www.deja.com/
Before you buy.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]




