2

I have the following listing from a page:

#include "vector.h"

// An axis-aligned bounding box
class AABB
{
  public:
    VECTOR P; //position
    VECTOR E; //x,y,z extents

    AABB( const VECTOR& p, const VECTOR& e): P(p) ,E(e) {}

    // ...

    const SCALAR min( long i ) const
    {

      return ((AABB*)this)->P[i] - ((AABB*)this)->E[i];
    }
    // ...
};

Now what I don't understand is, what is accessed by min() with a long value. I've looked into vector.hand found out that the square-bracket operator is overloaded:

class VECTOR
{
  public:
    SCALAR x,y,z; //x,y,z coordinates

    //...

    //index a component
    //NOTE: returning a reference allows
    //you to assign the indexed element
    SCALAR& operator [] ( const long i )
    {
      return *((&x) + i);
    }
    //...
};

Later it is used as:

// each axis
for( long i=0 ; i<3 ; i++ )
{
  if( A.max(i)<B.min(i) && v[i]<0 )
  {

So why is the x value reference incremented by i?
Please bear with me if this question is ridiculous easy, I am still a rookie. And if this isn't enough of information, I can provide the actual source

4

4 回答 4

3

It's not incremented.

&x  //<- address of member x
(&x) + i //<- address of member x shifted right by i SCALAR's
*((&x) + i) // the scalar value at that point

Hence *((&x) + i) returns the i'th scalar. x for 0, y for 1, z for 2.

于 2013-06-04T22:20:55.357 回答
3

This is called pointer arithmetic.

In the code, &x takes the address of x which is a pointer; adding i to that means that the pointer is incremented by sizeof(x) * i. Usually you do this to achieve the same effect as indexing into an array. For example, if you have

int arr[10];

then by writing &arr[0] + i you effectively index to the ith integer in the array. In some cases there might be some other type of contiguous memory block instead of a standard array.

This is not quite what happens in the case under question, because there is no array or other such memory block here. Instead the code assumes that the compiler will calculate a memory layout for VECTOR such that x, y, and z would be placed alongside in memory, simulating an array layout.

However this practice invokes undefined behavior according to C++ standard, so this implementation of VECTOR is flawed and should not be used.

于 2013-06-04T22:22:01.937 回答
2

The operation being done in operator[] is "pointer arithmetic" - where you use normal arithmetic operators (+ in this case) to navigate memory using a pointer (generally with arrays).

You can see some more examples of this technique here: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html

It should be noted that, if SCALAR is some non-array type, then I would argue that the code given is "dangerous", in that it assumes that x, y and z are going to be in adjacent memory locations, which is not guaranteed by standard C++. The result would be, if you try to use this code on a platform that doesn't guarantee this assumption, is that operator[] would at best return some undefined value, or at worst cause a segmentation fault.

于 2013-06-04T22:23:36.923 回答
1

That's pointer arithmetic.

In the VECTOR struct, the SCALAR members will likely (It's not guaranteed.) appear consecutively in memory, and the author of that code took advantage of that by just adding an index to the memory address of the first member in the struct (x).

This is how the input maps to the output:

  • 0 ... *(&x + 0) ... x
  • 1 ... *(&x + 1) ... y
  • 2 ... *(&x + 2) ... z

This was a pretty unsafe assumption by the author however :V.
(Padding bytes, order of members, etc...)

于 2013-06-04T22:21:05.617 回答