public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* reinterpret_casting a non-POD
@ 2008-08-16 12:31 Philip
  2008-08-17  4:08 ` Eljay Love-Jensen
  0 siblings, 1 reply; 2+ messages in thread
From: Philip @ 2008-08-16 12:31 UTC (permalink / raw)
  To: gcc-help

Given a simple but currently non-POD class such as:

struct Point
{
  float x, y, z;

  Point () {}
  Point (float x_, float y_, float z_): x (x_), y (y_), z (z_) {}
};

Is there any risk involved in the following operations?:

Point p;
float* pp = reinterpret_cast<float*> (&p);

void* buffer = // acquire memory
Point* points = reinterpret_cast<Point*> (buffer);
// do stuff that treats buffer as array of Points
float* floats = reinterpret_cast<float*> (points);

Thanks.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: reinterpret_casting a non-POD
  2008-08-16 12:31 reinterpret_casting a non-POD Philip
@ 2008-08-17  4:08 ` Eljay Love-Jensen
  0 siblings, 0 replies; 2+ messages in thread
From: Eljay Love-Jensen @ 2008-08-17  4:08 UTC (permalink / raw)
  To: Philip, GCC-help

Hi Philip,

I think the risks are...

*** Pointer aliasing may cause you problems.

*** Intra-structure padding may cause you problems.

*** Alignment requirements that are not fulfilled by your "acquire memory"
may cause you problems.

*** Even if it works on your machine, the non-portable code may cause you
problems if you ever port it, including upgrading compilers from the same
vendor on the same platform.

*** If the class is a general purpose SDK class, I'd strongly consider *not*
making the member functions inline, rather move their implementation out
into the Point.cpp file.  (If your downstream users are a captive audience,
such as you are making an SDK for your own team, or making an SDK which is
only used intra-company, then the issue is much less important.)  Plus, for
a general purpose SDK, I would implement the synthetic routines that the
compiler will generate for you, such as destructor, copy constructor, and
assignment operator, yada yada.  (I'd even go as far as consider the "next
step" and change Point to an interface-only class with virtual functions and
a static factory function, with the implementation class not exposed in the
SDK API.)

#define SOAPBOX

I'd fix those problems by trying to encapsulate the behavior you are trying
to do into the Point class itself.

I don't know what your preferred paradigm for getters/setters naming
convention, so I used the Objective-C / Cocoa -ish one.

I also added the Print/Scan and Write/Read pairs.  And the I/O streaming <<
and >> operator glue.

---------------------------------------- Point.h
// Probably not the best way to get a float NaN.
float const FloatNaN = 0.0f / 0.0f;

class Point
{
  float m[3];
public:
  Point() { m[0] = m[1] = m[2] = FloatNaN; }
  Point(float x, float y, float z) { m[0] = x; m[1] = y; m[2] = z; }
  float* AsFloatArray3() { return m; } // Exposes implementation.
  float X() const { return m[0]; }
  float Y() const { return m[1]; }
  float Z() const { return m[2]; }
  void SetX(float x) { m[0] = x; }
  void SetY(float y) { m[1] = y; }
  void SetZ(float z) { m[2] = z; }
  void Print(std::ostream&) const; // Human readable printer.
  void Scan(std::istream&); // Round-trip scan-from-print.
  void Write(std::ostream&) const; // Binary writer.
  void Read(std::istream&); // Binary reader.
};

inline
std::ostream& operator << (std::ostream& output, Point const& point)
{
  point.Print(output);
  return output;
}

inline
std::istream& operator >> (std::istream& input, Point& point)
{
  point.Scan(input);
  return input;
}
----------------------------------------

Here are some principles:

Put the code in your class, so that for the USERS of your class, it's easy
to use like butter.  Even if that means your class's implementation is ugly
in spots, it is better for the ugliness to be encapsulated in the class
rather than distributed amongst the users.  That's the primary target
audience of your class's API.

The primary target audience of your class's code is the poor maintenance
programmer (could be your future self a few years down the road) who has to
figure out your class, enhance your class, or debug it.  Make your class as
programmer friendly as possible.  Lots of useful comments.  Nice, consistent
formatting.  Don't make statements unnecessarily convoluted.  Trust the
compiler's optimizer.  The only time you should employ "befuddling code" is
if profiling indicates that -- for performance reasons -- the code needs to
have loops manually unrolled or some other heinous obfuscation techniques.
Make sure those manual machinations are well documented, and maybe keep the
"slow" routine around for sanity checking and self-testing.  [The above
Point class is *NOT* a showcase example of programmer friendly formatting.
But it's a pretty simple example, where making it "programmer friendly"
would make it look bloated with unnecessary busy-comments.  Good for
increasing kLOC, if you are paid by the kLOC.]

#undef SOAPBOX

HTH,
--Eljay

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-08-16 12:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-16 12:31 reinterpret_casting a non-POD Philip
2008-08-17  4:08 ` Eljay Love-Jensen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).