treating set of member data as an array

M

mojmir

hello,

i've just encountered following piece of code:

struct Vector
{
float x, y, z;

inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};

i think it can work due to placement in memory, but i'd like to ask
you
whether it is a good and safe programming practice or not.

many thanks in advance,
mojmir
 
Z

Zeppe

mojmir said:
hello,

i've just encountered following piece of code:

struct Vector
{
float x, y, z;

inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};

i think it can work due to placement in memory, but i'd like to ask
you
whether it is a good and safe programming practice or not.

many thanks in advance,
mojmir

the only fact that you don't know if it's a good practice, it means that
is not a good practice (i.e., adds complexity where it can be avoided).
Anyway, afaik is not safe due to the fact that there cen be alignement
requirements for x, y, z.

Regards,

Zeppe
 
G

Guest

hello,

i've just encountered following piece of code:

struct Vector
{
float x, y, z;

inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};

i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.

The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:

struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}
};

The body of the [] operator can be replaced with if-statements if you
like that better.
 
T

terminator

i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.

The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:

struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}

};

The body of the [] operator can be replaced with if-statements if you
like that better.

Wait a sec!!! why not just a simple array?

enum{x=0,y=1,z=2};
typedef float vec3d[z+1];

vec3d v={1,2,3};
{//in some function
v[x]=....
v[y]=...
v[z]=...
}

thanks,
FM.
 
T

terminator

On 2007-10-25 14:23, mojmir wrote:
hello,
i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.
The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:
struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}

The body of the [] operator can be replaced with if-statements if you
like that better.
- Show quoted text -

Wait a sec!!! why not just a simple array?

enum{x=0,y=1,z=2};
typedef float vec3d[z+1];

vec3d v={1,2,3};
{//in some function
v[x]=....
v[y]=...
v[z]=...

}

thanks,
FM.- Hide quoted text -
because it is unsecure on array bounds.
 
H

hodges.r

On 2007-10-25 14:23, mojmir wrote:
hello,
i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.
The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:
struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}
};
The body of the [] operator can be replaced with if-statements if you
like that better.
Wait a sec!!! why not just a simple array?
enum{x=0,y=1,z=2};
typedef float vec3d[z+1];
vec3d v={1,2,3};
{//in some function
v[x]=....
v[y]=...
v[z]=...

thanks,
FM.- Hide quoted text -

because it is unsecure on array bounds.

and "return *(&x + i);" isn't ???
 
G

Guest

On 2007-10-25 14:23, mojmir wrote:

i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.
The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:
struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}

The body of the [] operator can be replaced with if-statements if you
like that better.
- Show quoted text -
Wait a sec!!! why not just a simple array?
enum{x=0,y=1,z=2};
typedef float vec3d[z+1];
vec3d v={1,2,3};
{//in some function
v[x]=....
v[y]=...
v[z]=...

thanks,
FM.- Hide quoted text -

because it is unsecure on array bounds.

and "return *(&x + i);" isn't ???

Not with a proper assert on the value of i.
 
M

mojmir

because it is unsecure on array bounds.
Not with a proper assert on the value of i.

yes, the assert is there.

so in my case it's working because sizeof(float)=4, sizeof(Vector)=12
and the
machine word is 32b. but if i move to 64bit platform for example, the
&x+1 will
eventually point to 4 padding bytes inserted by compiler, right?

regards,
mojmir
 
T

terminator

On 2007-10-25 14:23, mojmir wrote:
hello,
i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.
The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:
struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}
};
The body of the [] operator can be replaced with if-statements if you
like that better.
--
Erik Wikström- Hide quoted text -
- Show quoted text -
Wait a sec!!! why not just a simple array?
enum{x=0,y=1,z=2};
typedef float vec3d[z+1];
vec3d v={1,2,3};
{//in some function
v[x]=....
v[y]=...
v[z]=...
}
thanks,
FM.- Hide quoted text -
because it is unsecure on array bounds.
and "return *(&x + i);" isn't ???

Not with a proper assert on the value of i.

your solution never overruns the array bounds even in the absence of
assert ,because it is a conditional that only returns a refrence to
either of x,y or z.In fact if you remove your assertion ,code will run
faster ; for some itegers it returns x , for some other returns y and
for the rest returns z.I have reorderd your index operator this way:

float& Vector::eek:perator[](unsigned i){
return i == 0 ? x :( i == 1 ? y : z);
};

now 0 means x, 1 means y and anything else means z.

regards,
FM.
 
T

terminator

yes, the assert is there.

so in my case it's working because sizeof(float)=4, sizeof(Vector)=12
and the
machine word is 32b. but if i move to 64bit platform for example, the
&x+1 will
eventually point to 4 padding bytes inserted by compiler, right?

consider:

class A a;
size_t n;

then following is always true:

&A+n == static_cast<A*>(static_cast<size_t>(&A)+n*sizeof(A))

So your code works fine provided that overflow does not happen (that
is you do not index the vector with n > 2).But Erik`s code never
overflows even if the assertion is omitted.

regards,
FM.
 
J

James Kanze

i've just encountered following piece of code:
struct Vector
{
float x, y, z;
inline float & operator[] (size_t i)
{
assert(i<3);
return *(&x + i);
}
};
i think it can work due to placement in memory, but i'd like to ask
you whether it is a good and safe programming practice or not.
The important word is *can*. The above code can work due to placement in
memory, but it can also not work due to placement in memory. A safer
version could look like this:
struct vector
{
float x, y, z;
float& operator[](size_t i)
{
assert(0 <= i && i <3);
return i < 2 ? i == 0 ? x : y : z;
}
};
The body of the [] operator can be replaced with if-statements
if you like that better.

Or a switch. Alternatively, you could declare an array, and
provide functions "x() { return values[ 0 ] ; }", etc.
 
J

James Kanze

yes, the assert is there.

so in my case it's working because sizeof(float)=4,
sizeof(Vector)=12 and the machine word is 32b.

No. It works because it happens to work.
but if i move to 64bit platform for example, the &x+1 will
eventually point to 4 padding bytes inserted by compiler,
right?

Probably not. In practice, I can't think of a reasonable
implementation where it wouldn't work. But according to the
standard, it is undefined behavior, and an implementation is not
required to make it work. And while I don't know of an
implementation off hand where it won't work, I don't know of one
which guarantees it (i.e. explicitly defines the behavior)
either.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,197
Messages
2,571,040
Members
47,635
Latest member
SkyePurves

Latest Threads

Top