473,412 Members | 2,012 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,412 software developers and data experts.

is this portable

Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

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

Thanx
Martin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #1
32 1668

"Martin Vorbrodt" <mv*******@poczta.onet.pl> wrote in message
news:ck**********@news.onet.pl...
Hi there. Is this code portable between platforms? Is it also 100%
standard
compliant?


No, and no.

But why would you want to write code like this?

john
Jul 22 '05 #2
John Harrison wrote:
Martin Vorbrodt wrote:
Hi there. Is this code portable between platforms? Is it also 100%
standard
compliant?


No, and no.


The data members were within one private: tag, so their order is
well-defined, and their paddings are implementation-defined.

The second rule makes them non-portable.

So, John, why are they not 100% standard compliant?
But why would you want to write code like this?


Because OpenGL rewards you to. It permits many variations of its methods to
take an array of indices as a primitive "point object".

The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #3
* Phlip:
John Harrison wrote:
Martin Vorbrodt wrote:

Hi there. Is this code portable between platforms? Is it also 100%
standard
compliant?


No, and no.


So, John, why are they not 100% standard compliant?


The program has undefined effect due to invalid pointer arithmetic
(via indexing). My experience is that you'll probably respond to
that by demanding some further justification. And to respond to
that response in advance, look up the rules for valid pointer values.

But why would you want to write code like this?


Because OpenGL rewards you to. It permits many variations of its methods to
take an array of indices as a primitive "point object".

The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.


That's very bad advice because undefined effect is unnecessary.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #4

"Phlip" <ph*******@yahoo.com> wrote in message
news:uL*****************@newssvr16.news.prodigy.co m...
John Harrison wrote:
Martin Vorbrodt wrote:
> Hi there. Is this code portable between platforms? Is it also 100%
> standard
> compliant?


No, and no.


The data members were within one private: tag, so their order is
well-defined, and their paddings are implementation-defined.

The second rule makes them non-portable.

So, John, why are they not 100% standard compliant?


I guess it depends what you mean by standard compliant. I said no because
dubious pointer arithmetic in the Point class potentially allows access to
padding bytes resulting in undefined behaviour.

But why would you want to write code like this?
Because OpenGL rewards you to. It permits many variations of its methods
to
take an array of indices as a primitive "point object".


I can't see the advantage of the OP's code over this, which is portable and
standards compliant

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

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

private:
int _val[3];
};
The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.


The OP's code is very likely to work in practice, but it seems to me that
100% complaint code could do as well, and should be preferred.

john
Jul 22 '05 #5
John Harrison wrote:
"Phlip" <ph*******@yahoo.com> wrote in message
news:uL*****************@newssvr16.news.prodigy.co m...
John Harrison wrote:

Martin Vorbrodt wrote:

Hi there. Is this code portable between platforms? Is it also 100%
standard
compliant?

No, and no.


The data members were within one private: tag, so their order is
well-defined, and their paddings are implementation-defined.

The second rule makes them non-portable.

So, John, why are they not 100% standard compliant?

I guess it depends what you mean by standard compliant. I said no because
dubious pointer arithmetic in the Point class potentially allows access to
padding bytes resulting in undefined behaviour.
But why would you want to write code like this?


Because OpenGL rewards you to. It permits many variations of its methods
to
take an array of indices as a primitive "point object".

I can't see the advantage of the OP's code over this, which is portable and
standards compliant

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

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

private:
int _val[3];
};

The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.

The OP's code is very likely to work in practice, but it seems to me that
100% complaint code could do as well, and should be preferred.

john


I thought identifiers with leading underscores were reserved
for the compiler / implementation's usage. If this is so,
then it is not portable (because some compilers may have
identifiers with those names).

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library

Jul 22 '05 #6
>
I thought identifiers with leading underscores were reserved
for the compiler / implementation's usage. If this is so,
then it is not portable (because some compilers may have
identifiers with those names).


Only when those identifiers are at namespace scope. Within a class or a
function they are OK.

john
Jul 22 '05 #7

"Thomas Matthews" <Th*************************@sbcglobal.net> wrote in
message news:41**************@sbcglobal.net...
John Harrison wrote:
"Phlip" <ph*******@yahoo.com> wrote in message
news:uL*****************@newssvr16.news.prodigy.co m...
John Harrison wrote:
Martin Vorbrodt wrote:

>Hi there. Is this code portable between platforms? Is it also 100%
>standard
>compliant?

No, and no.

The data members were within one private: tag, so their order is
well-defined, and their paddings are implementation-defined.

The second rule makes them non-portable.

So, John, why are they not 100% standard compliant?

I guess it depends what you mean by standard compliant. I said no because dubious pointer arithmetic in the Point class potentially allows access to padding bytes resulting in undefined behaviour.
But why would you want to write code like this?

Because OpenGL rewards you to. It permits many variations of its methods
to
take an array of indices as a primitive "point object".

I can't see the advantage of the OP's code over this, which is portable and standards compliant

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

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

private:
int _val[3];
};

The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.

The OP's code is very likely to work in practice, but it seems to me that 100% complaint code could do as well, and should be preferred.

john


I thought identifiers with leading underscores were reserved
for the compiler / implementation's usage.


Only those at namespace or 'global' scope.

However, I've adopted the practice of not using them at
all, obviating the need to even consider the details of
rules like this.

-Mike
Jul 22 '05 #8
John Harrison wrote:
I guess it depends what you mean by standard compliant. I said no because
dubious pointer arithmetic in the Point class potentially allows access to padding bytes resulting in undefined behaviour.
That's implementation-defined. But I have not read the other posts yet...
I can't see the advantage of the OP's code over this, which is portable and standards compliant
I added the syntactic sugar the OP wanted:
class Point {
public:
enum COORDS { X = 0, Y, Z };
int &x_;
int &y_;
int &z_;
Point(int x, int y, int z) : x_(_val[X]),
y_(_val[Y]),
z_(_val[Z]) {
_val[X] = x;
_val[Y] = y;
_val[Z] = z;
}

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

private:
int _val[3];
};


New question: Is taking a reference to the storage where a variable will be
before it initializes defined?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #9

"Phlip" <ph*******@yahoo.com> wrote in message
news:Us*****************@newssvr16.news.prodigy.co m...
John Harrison wrote:
I guess it depends what you mean by standard compliant. I said no because dubious pointer arithmetic in the Point class potentially allows access to
padding bytes resulting in undefined behaviour.


That's implementation-defined.


Which renders it unportable.
But I have not read the other posts yet...
I can't see the advantage of the OP's code over this, which is portable and
standards compliant


I added the syntactic sugar the OP wanted:
class Point {
public:
enum COORDS { X = 0, Y, Z };


int &x_;
int &y_;
int &z_;
Point(int x, int y, int z)

: x_(_val[X]),
y_(_val[Y]),
z_(_val[Z])
{
_val[X] = x;
_val[Y] = y;
_val[Z] = z;
}

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

private:
int _val[3];
};


New question: Is taking a reference to the storage where a variable will

be before it initializes defined?


AFAIK, it's perfectly legal, just don't try to evaluate the
object to which it refers until that object has been assigned
a value. IMO this is the same thing as declaring a reference
parameter to a function, which of course is fine.

-Mike
Jul 22 '05 #10
Alf P. Steinbach wrote:
The program has undefined effect due to invalid pointer arithmetic
(via indexing). My experience is that you'll probably respond to
that by demanding some further justification. And to respond to
that response in advance, look up the rules for valid pointer values.


Point to a valid object, NULL, or one off the end of an array..? Nope - not
gonna ask.

(I'm still waiting to hear if you found a real reason to disliked my TEST_
macro, besides I wrote it.)
The OP is advised to assert() that the size of Point equals the size of
three ints, and keep going. Unless if John can talk him out of it.


That's very bad advice because undefined effect is unnecessary.


Code dealing with Points, such as OpenGL code, typically undergoes sick
optimizations. Naturally I have seen worse than my bad advice.

Even applying my other post might degrade performance, when the compiler
can't optimize the references away fully.

Oh, and would those references make the Point a non-PODs? So the pointer
trick might have another reason to be less defined?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #11
* Phlip:

(I'm still waiting to hear if you found a real reason to disliked my TEST_
macro, besides I wrote it.)


Well, I dislike macros, so in the context of what would be _ideal_ I dislike
macro-based code -- but in the context of getting the job done, if it works,
don't fix it... ;-) There's also the question of learning curve both for the
one who implements the thing (that doesn't apply to you here, but in general)
and for those using it. So in that non-C++ perspective I think it's fine, a
Good Idea (TM), because it's much better to have automated testing than not.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #12
Mike Wahler wrote:
That's implementation-defined.


Which renders it unportable.


Sorry - I didn't hear "portable to any conceivable C++ platform". Hence the
assert(sizeof) thing to simply raise an alarm when the portability envelop
is crossed. But there I go again, helping solve the outer problem instead of
the exact question...

The OP is advised to write code whose legality can be trivially determined,
and to profile various kinds of statements to learn which ones are optimal.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #13

"Phlip" <ph*******@yahoo.com> wrote in message
news:Us*****************@newssvr16.news.prodigy.co m...
John Harrison wrote:
I guess it depends what you mean by standard compliant. I said no because
dubious pointer arithmetic in the Point class potentially allows access to
padding bytes resulting in undefined behaviour.


That's implementation-defined. But I have not read the other posts yet...


OK my bad, I didn't look it up.
I can't see the advantage of the OP's code over this, which is portable

and
standards compliant


I added the syntactic sugar the OP wanted:
class Point {
public:
enum COORDS { X = 0, Y, Z };


int &x_;
int &y_;
int &z_;
Point(int x, int y, int z)

: x_(_val[X]),
y_(_val[Y]),
z_(_val[Z])
{
_val[X] = x;
_val[Y] = y;
_val[Z] = z;
}

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

private:
int _val[3];
};


Are you sure? In his original post he as _x, _y and _z as private.

In any case I don't consider the price worth paying.

john
Jul 22 '05 #14

"Phlip" <ph*******@yahoo.com> wrote in message
news:5S*****************@newssvr16.news.prodigy.co m...
Mike Wahler wrote:
That's implementation-defined.
Which renders it unportable.


Sorry - I didn't hear "portable to any conceivable C++ platform".


I heard "is this portable?" and "is this 100% standard compliant?"
Hence the
assert(sizeof) thing to simply raise an alarm when the portability envelop
is crossed. But there I go again, helping solve the outer problem instead of the exact question...
If what you wrote helps anyone, that's great.
The OP is advised to write code whose legality can be trivially determined, and to profile various kinds of statements to learn which ones are

optimal.

Agreed.

-Mike
Jul 22 '05 #15
* Martin Vorbrodt:
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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]; }
No (because of padding & alignment issues), and no (it's Undefined Behavior).

private:
int _x, _y, _z;
};


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #16
"Martin Vorbrodt" <mv*******@poczta.onet.pl> wrote in message news:<ck**********@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! ]
Jul 22 '05 #17
Hi,

Martin Vorbrodt wrote:
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

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


No, it is no safe. There may be padding between the members and your
indexing operator assumes that the members are placed one after another
in memory. This is not guaranteed (but may happen to work on many
platforms).

What about this:

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

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

private:
int coords_[3];
};

--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #18
"Martin Vorbrodt" <mv*******@poczta.onet.pl> wrote in message news:<ck**********@news.onet.pl>...
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

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


Pointer arithmetic is effective for continuous memory arrangement. I
don't think that the standard say something how to arrange class
members, _x, _y, and _z, on memory. Therefore your code is not
guaranteed to work, although I think it works in many cases.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #19
In article <ck**********@news.onet.pl>, Martin Vorbrodt
<mv*******@poczta.onet.pl> wrote:
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

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

I can't name a compiler on which it will fail, but the compiler is
permitted to insert padding of its choice between _x,_y,_z and is
not permitted to do so with an int array. That said why not just provide
three access inlined access function members??

class Point
{
// ...
public
int X() const {return _x;}
int Y() const {return _y;}
int Z() const {return _z;}
};

This is portable and unless you prohibit inliniing it willl be at least
as efficient.
Point p(1,2,3);
std::cout << p.X() << ',' << p.Y() << ',' << p.Z() << '\n';

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #20
> Hi there. Is this code portable between platforms? Is it also 100% standard
compliant? Is it save to get the address of the first member, and do pointer arithmetic
on it to get to all 3 elements?


You are assuming that the three members will be allocated contiguously
and hence access it using array indexing from the address of first
member. Though standard (9.2 para 12) ensures that "a (non-union)
class declared without an intervening access-specifier are allocated
so that later members have higher addresses within a class object",
the problem is "Implementation alignment requirements might cause two
adjacent members not to be allocated immediately after each other".
And treating class members as if it were an array doing pointer
arithmetic is undefined behaviour, and hence is unsafe, and
non-portable.

-Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #21
Martin Vorbrodt wrote:
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

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


No, there may be padding between _x, _y and _z.

-- James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #22
In article <60**************************@posting.google.com >, Chris
Uzdavinis <cu****@gmail.com> writes
"Martin Vorbrodt" <mv*******@poczta.onet.pl> wrote in message news:<ck**********@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.


And though it might work in the context of a class, it is a dangerous
way to think. I once had to do major maintenance on some C code because
the original author assumed that:

int a, array[10];

And used that assumption for 11 global combinations of simple and array
variable.
allowed him to access array[0] as a[1], which was untrue on the compiler
I was using (I think it put arrays somewhere else entirely to minimise
stack use) In C++ you can do something like this:

int array[11];
int & a = array[0];

Or in your case, if you really want to go down this path:

int data[3]
int & _x;
int & _y;
int & _z;

and define the relationship in the ctor init list. But I cannot imagine
what it would gain you.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #23

"Chris Uzdavinis" <cu****@gmail.com> wrote in message news:60**************************@posting.google.c om...
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.)


And it has the (IMO) additional benefit of not implicitly casting
the enum to an int.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #24
Alf P. Steinbach wrote:
* Martin Vorbrodt:
> Hi there. Is this code portable between platforms? Is it also 100% standard > compliant?
>
> #include <iostream>
> using namespace std;
>
> 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]; }


No (because of padding & alignment issues), and no (it's Undefined

Behavior).

I think this is a "yes". Point is a PODs, and padding is
implementation-defined. Hence, on platforms where it's not undefined
behavior, it's well-defined.
> private:
> int _x, _y, _z;
> };


--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #25
* Phlip:
Alf P. Steinbach wrote:
> * Martin Vorbrodt:
> > Hi there. Is this code portable between platforms? Is it also 100%
> standard compliant?
> >
> > #include <iostream>
> > using namespace std;
> >
> > 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 (because of padding & alignment issues), and no (it's Undefined
> Behavior).


I think this is a "yes". Point is a PODs, and padding is
implementation-defined. Hence, on platforms where it's not undefined
behavior, it's well-defined.


The term "Undefined Behavior" usually refers to the Holy Standard, and that's
the way I used it -- UB in that sense is absolute, not platform-dependent.

As I understand it what you mean by "Undefined Behavior", in this case, is
whether a given C++ implementation defines the behavior.

That does not affect portability between platforms (the first "no"), nor does
it affect standard compliance (the second "no").

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #26
Alf P. Steinbach wrote:
The term "Undefined Behavior" usually refers to the Holy Standard, and that's the way I used it -- UB in that sense is absolute, not platform-dependent.
As I understand it what you mean by "Undefined Behavior", in this case, is
whether a given C++ implementation defines the behavior.

That does not affect portability between platforms (the first "no"), nor does it affect standard compliance (the second "no").


No, I mean "the implementors shall define the padding in a PODs." Defined
behavior. _Not_ "whatever my compiler happens to do."

I don't know why nobody mentioned PODs in the original answers. They cover
this situation.

AFAIK, x[1] is the same as i[x] is the same as *(x + 1), hence IF a pointer
points to a valid object, dereferencing the pointer is defined, hence
indexing the pointer can also be defined.

The IF part is covered by the rules for a PODs and for implementation
defined padding rules.

And I don't have the Standard to hand, so I await a real Language Lawyer to
trump us both (without the moderation delay).

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #27
"Martin Vorbrodt" <mv*******@poczta.onet.pl> wrote in message news:<ck**********@news.onet.pl>...
Hi there. Is this code portable between platforms? Is it also 100% standard
compliant?

#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

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

Thanx
Martin

....

Whether it's standard or not, it's very desirable that this sort
of code should work with a compiler that's going to be used in
an embedded environment. It's a fairly common technique to use
a struct to represent the register map of a memory-mapped IC, then
cast the IC's base address to be a pointer to the struct type.

More generally, there is alot of legacy C code that assumes that
if two structs have a sequence of data members as a "common prefix",
then these data members will be at the same offsets in the two
structs. It's kind of a neaderthal version of a base class.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #28
* Phlip:
Alf P. Steinbach wrote:
The term "Undefined Behavior" usually refers to the Holy Standard, and that's
the way I used it -- UB in that sense is absolute, not

platform-dependent.

As I understand it what you mean by "Undefined Behavior", in this case, is
whether a given C++ implementation defines the behavior.

That does not affect portability between platforms (the first "no"), nor

does
it affect standard compliance (the second "no").


No, I mean "the implementors shall define the padding in a PODs." Defined
behavior. _Not_ "whatever my compiler happens to do."


There is no such wording in the standard.
I don't know why nobody mentioned PODs in the original answers. They cover
this situation.
PODness isn't relevant to the questions asked (portability, conformance).
AFAIK, x[1] is the same as i[x] is the same as *(x + 1),
Correct for the built-in indexing operator, yes.

hence IF a pointer
points to a valid object, dereferencing the pointer is defined,
Correct.

hence indexing the pointer can also be defined.
Correct apart from the word "hence".

Can be defined, yes.

Is defined in general, no.

The IF part is covered by the rules for a PODs
Incorrect.

and for implementation defined padding rules.
Incorrect.

And I don't have the Standard to hand, so I await a real Language Lawyer to
trump us both (without the moderation delay).


That would probably not have passed moderation in clc++m, which is why
it was posted here?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #29
Walt Karas wrote:
Whether it's standard or not, it's very desirable that this sort
of code should work with a compiler that's going to be used in
an embedded environment. It's a fairly common technique to use
a struct to represent the register map of a memory-mapped IC, then
cast the IC's base address to be a pointer to the struct type.
The technique must have been provided by the specific implementation,
which defines the (originally undefined) behaviour and knows what it's
doing. Therefore, it neither is portable nor should be portable. The
desirability does not lead to the necessity of the standard's support.
More generally, there is alot of legacy C code that assumes that
if two structs have a sequence of data members as a "common prefix",
then these data members will be at the same offsets in the two
structs. It's kind of a neaderthal version of a base class.


I would say that, if they wanted to emulate inheritance in C, they
should have made the common (base) part into a struct and let it
included as the first member of each derived ones.

struct base { /* ... */ };
struct derived_A { struct base base_part; /* A part ... */ };
struct derived_B { struct base base_part; /* B part ... */ };

struct derived_A* pD = /* get some derived object */;
struct base* pB = &pD->base_part;

Isn't this much better than relying on undefined behaviour?

I'm not sure whether "(struct base*) pD" is guaranteed to work or not,
though.

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #30
Seungbeom Kim <mu******@bawi.org> wrote in message
news:<ck**********@news.Stanford.EDU>...
Walt Karas wrote:
Whether it's standard or not, it's very desirable that this sort of
code should work with a compiler that's going to be used in an
embedded environment. It's a fairly common technique to use a
struct to represent the register map of a memory-mapped IC, then
cast the IC's base address to be a pointer to the struct type. The technique must have been provided by the specific implementation,
which defines the (originally undefined) behaviour and knows what it's
doing. Therefore, it neither is portable nor should be portable. The
desirability does not lead to the necessity of the standard's support. More generally, there is alot of legacy C code that assumes that if
two structs have a sequence of data members as a "common prefix",
then these data members will be at the same offsets in the two
structs. It's kind of a neaderthal version of a base class.

I would say that, if they wanted to emulate inheritance in C, they
should have made the common (base) part into a struct and let it
included as the first member of each derived ones.
The question isn't so much what you should do, today. Today, if you
want base classes, it shouldn't be to hard to find a C++ compiler, and
do them right.

The question is what people actually did, many years ago, before there
was even a C standard. The C++ standard explicitly contains support for
common initial sequences, at least in certain conditions, because C
gives that support. And C gives it because it was a common technique in
C programs when C was being standardized.
struct base { /* ... */ };
struct derived_A { struct base base_part; /* A part ... */ };
struct derived_B { struct base base_part; /* B part ... */ }; struct derived_A* pD = /* get some derived object */;
struct base* pB = &pD->base_part; Isn't this much better than relying on undefined behaviour?
In one frequent case, "struct base" was actually just an enum, e.g.:

enum NodeType
{
nt_constant,
nt_variable,
nt_operator,
/* ... */
} ;

struct AbstractNode { NodeType type ; } ;
struct ConstantNode { NodeType type ; /* ... */ } ;
struct VariableNode { NodeType type ; /* ... */ } ;

The code would be something like:

void
processNode( AbstractNode* node )
{
switch ( node->type )
{
case nt_constant :
processConstantNode( (ConstantNode*)node ) ;
break ;
/* ... */
}
}
I'm not sure whether "(struct base*) pD" is guaranteed to work or not,
though.


I'm not sure in this particular case, but there are cases where it is
guaranteed. In practice, it will work, and things like the above were
not all that rare before we got C++.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #31
Seungbeom Kim <mu******@bawi.org> wrote in message news:<ck**********@news.Stanford.EDU>...
Walt Karas wrote:
Whether it's standard or not, it's very desirable that this sort
of code should work with a compiler that's going to be used in
an embedded environment. It's a fairly common technique to use
a struct to represent the register map of a memory-mapped IC, then
cast the IC's base address to be a pointer to the struct type.


The technique must have been provided by the specific implementation,
which defines the (originally undefined) behaviour and knows what it's
doing. Therefore, it neither is portable nor should be portable. The
desirability does not lead to the necessity of the standard's support.
More generally, there is alot of legacy C code that assumes that
if two structs have a sequence of data members as a "common prefix",
then these data members will be at the same offsets in the two
structs. It's kind of a neaderthal version of a base class.


I would say that, if they wanted to emulate inheritance in C, they
should have made the common (base) part into a struct and let it
included as the first member of each derived ones.

struct base { /* ... */ };
struct derived_A { struct base base_part; /* A part ... */ };
struct derived_B { struct base base_part; /* B part ... */ };

struct derived_A* pD = /* get some derived object */;
struct base* pB = &pD->base_part;

Isn't this much better than relying on undefined behaviour?

I'm not sure whether "(struct base*) pD" is guaranteed to work or not,
though.


Having the common prefix be a struct is more readable, but it
isn't really relevant to the issue of whether the compiler is
permitted to reorder data members of a class in the memory
layout of class instances.

Obviously there are cases where reordering data members would
save wasted "pad" bytes, for example:

class X
{
char a;
int b;
char c;
};

To avoid breaking old C code, maybe the rule should be
that reordering is permitted except in structs with no base
classes and no virtual functions.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #32
Martin Vorbrodt wrote:
Is this code portable between platforms?
Yes.
Is it also 100% standard compliant?
No.
#include <iostream>
using namespace std;

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;
};

int main() {
Point p(1, 2, 3);

cout << p[Point::X] << endl;
cout << p[Point::Y] << endl;
cout << p[Point::Z] << endl;
}

Is it [safe] to get the address of the first member,
and do pointer arithmetic on it to get to all 3 elements?


Probably.
Jul 22 '05 #33

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: James Harris | last post by:
Hi, Can someone recommend a book that will teach me how to approach C programming so that code is modularised, will compile for different environments (such as variations of Unix and Windows),...
22
by: SeeBelow | last post by:
Is there any way, in C, of interacting with a running program, but still using code that is portable, at least between linux and Windows? By "interacting" it could be something as simple as...
10
by: Jason Curl | last post by:
Dear C group, I'm very interested in writing portable C, but I only have GNU, Sparc and Cygwin to compile on. What I find is the biggest problem to writing portable C is what headers to...
8
by: suresh_C# | last post by:
Dear All, What is difference between Portable Executable (PE) file and a Assembly? Thanks, Mahesh
2
by: Tull Clancey | last post by:
Hi all. I'm nearing completion of a host app that needs to send data to, and receive data back from a portable, an HP device. The application running on the portable will be a .net application....
131
by: pemo | last post by:
Is C really portable? And, apologies, but this is possibly a little OT? In c.l.c we often see 'not portable' comments, but I wonder just how portable C apps really are. I don't write...
162
by: Richard Heathfield | last post by:
I found something interesting on the Web today, purely by chance. It would be funny if it weren't so sad. Or sad if it weren't so funny. I'm not sure which. ...
409
by: jacob navia | last post by:
I am trying to compile as much code in 64 bit mode as possible to test the 64 bit version of lcc-win. The problem appears now that size_t is now 64 bits. Fine. It has to be since there are...
10
by: bramnizzle | last post by:
I don't know if this is the right thread or not, but... In my endless pursuit to hold on to my dinosaur laptop (Dell 1100 Inspiron - circa 2004)...I want to keep as much space free for my...
23
by: asit | last post by:
what is the difference between portable C, posix C and windows C ???
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.