Re: is this portable

From: Chris Uzdavinis (cuzdav_at_gmail.com)
Date: 10/10/04


Date: 10 Oct 2004 05:38:06 -0400


"Martin Vorbrodt" <mvorbrodt@poczta.onet.pl> wrote in message news:<ck6adr$her$1@news.onet.pl>...
> Hi there. Is this code portable between platforms? Is it also 100% standard
> compliant?
...

> class Point {
> public:
> enum COORDS { X = 0, Y, Z };
> Point(int x, int y, int z) : _x(x), _y(y), _z(z) {}
>
> const int& operator[](COORDS c) const
> { return (&_x)[c]; }
>
> private:
> int _x, _y, _z;
> };

No. Absolutely not. The address of _x tells you where _x is located.
  It does not imply anything about the other members, and it's
undefined to use &x as the base pointer of an array, since it doesn't
point into one. You really don't want to use it as if it were one,
because that takes you into undefined territory.

If you do this, you're depending on compiler implementation detail
such as the order that the members are layed out in memory, and that
there's no padding bytes between the members. It goes without saying
that depending on compiler implementation details is not portable.

> Is it save to get the address of the first member, and do pointer arithmetic
> on it to get to all 3 elements?

Tricks like this may sometimes (unfortunately) work as expected, and
sometimes even so-called experts do them. But undefined behavior is
undefined behavior, and the appearance of "working" is one way
undefined behvaior manifests itself. This kind of coding is
needlessly dangerous and certain to eventually cause you harm. (That
is, it WILL break someday, on some platform, and you'll spend hours
debugging a problem that should not exist.) I suggest you write code
that is so obviously correct that you don't have to ask. For example:

   class Point {
   public:
            enum COORDS { X = 0, Y, Z };
            Point(int x, int y, int z) : _x(x), _y(y), _z(z) {}

            const int& operator[](COORDS c) const
            { switch(c) {
              case X: return _x;
              case Y: return _y;
              case Z: return _z;
              default: throw std::runtime_error("Invalid argument");
            }

   private:
            int _x, _y, _z;
   };

Or alternately,

   class Point {
   public:
            enum COORDS { X = 0, Y, Z };
            Point(int x, int y, int z) { xyz[X] = x; xyz[Y] = y; xyz[Z]
= z;}

            const int& operator[](COORDS c) const
            { return xyz[c]; }

   private:
            int xyz[3];
   };

In this second case, member xyz is an array and it's thereforce safe
to index into. (Assuming the argument to operator[] is in range, of
course.)

--
Chris
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Relevant Pages

  • Re: macro to access structures member
    ... foo1 is global object and thus all members are initialized to 0. ... is undefined behavior. ... Do you expect myOtherFunction to receive or? ... In calling anotherFunction() above, it is arbitrary whether foois ...
    (comp.lang.c)
  • Re: one-man company?
    ... Depending on where you live and what trade you practice, ... members of the "learned professions" are not permitted to ...
    (alt.usage.english)
  • Mail send when update
    ... Depending on the checks that the members of a project had ... activated on PWA, in order to communicate the changes, a ...
    (microsoft.public.project.pro_and_server)
  • Re: YEA, ok, this says a lot...
    ... And a host of other ethnic and vernacular terms. ... All are the largest members of the family of conical cup-mouthpiece brass known as Saxhorns. ... The names are used somewhat interchangeably, depending on what the manufacturer feels will sell them. ...
    (rec.arts.marching.drumcorps)
  • Re: macro to access structures member
    ... foo1 is global object and thus all members are initialized to 0. ... is undefined behavior. ... I expected to have member 'a' of teh structure 'struct foo' to be ... increment the value -- this was my expectation. ...
    (comp.lang.c)