From -2080896510493688121
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 109fba,b244bc9cfc4330f9
X-Google-Attributes: gid109fba,public
X-Google-Thread: f78e5,1e1d3ed27fda1584,start
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 1994-04-04 10:57:13 PST
Xref: gmd.de comp.lang.c++:51290 comp.std.c++:6312
Path: gmd.de!newsserver.jvnc.net!darwin.sura.net!math.ohio-state.edu!cs.utexas.edu!not-for-mail
From: jamshid@ses.com (Jamshid Afshar)
Newsgroups: comp.lang.c++,comp.std.c++
Subject: Re: casting class function addresses
Followup-To: comp.std.c++
Date: 4 Apr 1994 12:57:13 -0500
Organization: SES, Inc., Austin, TX, USA
Lines: 84
Sender: daemon@cs.utexas.edu
Message-ID: <9404041757.AA28726@ses.com>
References: <jpcauvin-020494115637@slip-15-2.ots.utexas.edu> <pjl.765206128@graceland.att.com> <41768@mindlink.bc.ca> <BWH.94Apr2122342@beach.cis.ufl.edu>
NNTP-Posting-Host: cs.utexas.edu

Redirected to comp.std.c++.

In article <jpcauvin-020494115637@slip-15-2.ots.utexas.edu>,
Roger L. Cauvin <jpcauvin@bongo.cc.utexas.edu> wrote:
>In article <BWH.94Apr2122342@beach.cis.ufl.edu>, bwh@beach.cis.ufl.edu
>(Brian Hook) wrote:
>: The reason that:
>:    int i = 2;
>;    double d = *(double *)&i;
>; Will fail is that values for doubles are stored differently than values
>: for ints, not just because of size differences.  If the above used "float"
>; instead of "double" and sizeof( int ) == sizeof( float ) it would still
>: fail because the bits within i would be interpreted incorrectly.

That is correct.  Imagine a floating point math processor which
signaled an error when an invalid bit-pattern was detected.  `d' might
actually be kept in one of the math processor's registers so running
the above code might crash the program, just like dereferencing a null
pointer might.

>Of *course* a coercion of double to int will not result in an intuitive
>conversion.  However, this is a far cry from the coercion causing a
>run-time error.
>Casting, and to an even greater extent, coercion, are fraught with dangers
>of losing significant bits, producing unintuitive conversions, and
>overwriting data.  Nonetheless, a simple coercion of one pointer type to
>another should not *itself* cause a run-time error.  What is done with the
>pointer *afterward* may.

What do you mean by "simple coercion of one pointer type to another"?
Where did you learn a distinction between the terms "coercion" and
"casting"?  K&R1, CPL2, and the June 1993 ANSI/ISO Working Paper all
seem to use the terms interchangeably.

Anyway, the above code definitely results in undefined behavior (eg,
run-time error).  You may cast any pointer to *object* (ie, NOT
pointers to members or pointers to regular functions) to another
pointer to object type.  While this pointer conversion may compile it
may crash at run-time if the object pointed to is not suitably
aligned, and alignment requirements are implementation-dependent.

	int i=2;
	double* dp = (double*)&i;  // even if you do nothing with dp, the
	                           // program can crash at this line

Imagine a 32-bit CPU which had a special register to store pointers to
objects which are aligned on a double word boundary.  The CPU might
crash when a value with non-zero least significant bits was stored in
the register.  The compiler might always align doubles on a double
words, but `i' might not be so aligned (even if it's the same size).

A pointer TO a pointer to a member may be converted to another pointer
to object type; after all, it is a pointer to object.  But like the
double* conversion above, such a conversion may result in a crash if
pointers to members have different alignment requirements (ie, are of
different sizes).  Some current C++ compilers can optionally, at the
expense of letting ptm casts work, optimize the size of ptms.  It's
still very uncertain whether ANSI/ISO will allow this optimization
(see the "Casting member function pointers" thread in comp.std.c++).
So, it's unclear whether the following code will result in undefined
behavior:

	typedef void (A::*AFP)();
	typedef void (B::*BFP)();
	void f( AFP a ) {
	   BFP* bfpp = (BFP*)&a;
	}

But, I think all this is pretty much moot because your code (in your
first article) actually dereferenced the pointer to pointer to member:

	void g( AFP a ) {
	   BFP bfp = *(BFP*)&a;   // definitely undefined run-time behavior
	}

You can't just treat the block of memory where a particular object is
stored like a block of memory containing another type of object (chars
being an exception).  I don't think it matters whether you even use
bfp, just like it doesn't matter whether the `d' from this article's
first example is used.

Jamshid Afshar
jamshid@ses.com



