[net.lang.c] Failure of "long x

ado@elsie.UUCP (Arthur David Olson) (06/29/86)

As I understand it, the code produced by some compilers from

	long x(cp)
	char * cp;
	{
		return *((long *) cp);
	}

will cause core dumps if the value of cp isn't "appropriately aligned".
When dealing with such compilers, you get to do something like

	long x(cp)
	char * cp;
	{
		long l;

		function_to_do_arbitrary_copying((char *) &l, cp, sizeof l);
		return l;
	}

to avoid core dumps.

Isn't this really a compiler bug?  Doesn't the cast in the
		return *((long *) cp);
give the compiler all the evidence it needs that it should, *on its own*,
produce code that's the equivalent of the function call?

Does the latest version of X3J11 have anything to say on the matter?
--
Bug/s is a Volkswagen/Warner Brothers trademark.
--
	UUCP: ..decvax!seismo!elsie!ado		ARPA: elsie!ado@seismo.ARPA
	DEC, VAX, Elsie & Ado are Digital, Borden & Shakespeare trademarks.

chris@umcp-cs.UUCP (Chris Torek) (06/29/86)

In article <6152@elsie.UUCP> ado@elsie.UUCP (Arthur David Olson) writes:
>As I understand it, the code produced by some compilers from
>
>	long x(cp)
>	char * cp;
>	{
>		return *((long *) cp);
>	}
>
>will cause core dumps if the value of cp isn't "appropriately aligned".

>...  Doesn't the cast in the
>		return *((long *) cp);
>give the compiler all the evidence it needs that it should, *on its own*,
>produce code that's the equivalent of the function call?

[\S = section symbol]

No.  K&R, Appendix A, \S 14.4, p.~210:

  14.4  Explicit pointer conversions
  ...
    A pointer to one type may be converted to a pointer to another
  type.  The resulting pointer may cause addressing exceptions
  upon use if the subject pointer does not refer to an object
  suitably aligned in storage. ...

While you are verifying this, take a look at \S 16.  I think it is
amusing that as long ago as 1978, K&R identified most of the major
portability problems that many people are now seeing for the first
time.  (The big one they left out of \S 16 is null-pointer derefer-
encing.)  You were warned, eight years ago!  :-)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

ark@alice.UucP (Andrew Koenig) (06/29/86)

> Isn't this really a compiler bug?  Doesn't the cast in the
> 		return *((long *) cp);
> give the compiler all the evidence it needs that it should, *on its own*,
> produce code that's the equivalent of the function call?

When you cast a pointer type to another pointer type,
you have stepped outside the bounds of the language.
The implementation is entitled to do as it pleases.

guy@sun.uucp (Guy Harris) (06/29/86)

> Isn't this really a compiler bug?  Doesn't the cast in the
> 		return *((long *) cp);
> give the compiler all the evidence it needs that it should, *on its own*,
> produce code that's the equivalent of the function call?

A piece of software has a "bug" if it's supposed to do something and it
doesn't; for instance, if it's supposed to generate correct code and it
generates incorrect code instead.  The C compiler isn't *supposed* to do
unaligned copying in circumstances like this, so it can hardly be a "bug" if
it doesn't.

> Does the latest version of X3J11 have anything to say on the matter?

The August 11, 1985 draft says:

	C.3.3.2 Address and indirection operators

	...

	Semantics

	...

	     If an invalid value has been assigned to the pointer, the
	behavior of the unary * operator is undefined.  Such invalid
	values include ... *an address inappropriately aligned for the
	type of the object pointed to*...

I *very* sincerely doubt this has been changed in any later drafts.  Such
dereferences are uncommon occurrences, and a programmer can damn well write
their own code to do the unaligned copy.

So a C compiler which doesn't generate unaligned copies is perfectly within
its rights to do so, and has no bug.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

john@frog.UUCP (John Woods, Software) (07/01/86)

> 	long x(cp)
> 	char * cp;
> 	{return *((long *) cp); }
> will cause core dumps if the value of cp isn't "appropriately aligned".
> When dealing with such compilers, you get to do something like
> 	long x(cp)
> 	char * cp;
> 	{	long l;
> 		function_to_do_arbitrary_copying((char *) &l, cp, sizeof l)
> 		return l;
> 	}
> to avoid core dumps.
> Isn't this really a compiler bug?

No, I'd say not.  The compiler is doing just exactly what you said in the
first case.  What you said was something stupid, ergo it does something
stupid.  Lint will complain about the construction, declaring there to be
a "possible pointer alignment problem" (you bet!).

(by the way, an in-line copy would be faster than the function call (except
perhaps on machines where function calls take negative time :-) )).


--
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101
...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA

"Imagine if every Thursday your shoes exploded if you tied them the usual way.
This happens to us all the time with computers, and nobody thinks of
complaining."
			Jeff Raskin, interviewed in Doctor Dobb's Journal

kab@reed.UUCP (Kent Black) (07/03/86)

In article <6152@elsie.UUCP> ado@elsie.UUCP (Arthur David Olson) writes:
>As I understand it, the code produced by some compilers from
>
>	long x(cp)
>	char * cp;
>	{
>		return *((long *) cp);
>	}
>
>will cause core dumps if the value of cp isn't "appropriately aligned".
>
>Isn't this really a compiler bug?  Doesn't the cast in the
>		return *((long *) cp);
>give the compiler all the evidence it needs that it should, *on its own*,
>produce code that's the equivalent of the function call?
 
Oh, am I in over my head. . .

If a (char *) can reference any `byte' of memory, and a (long *) can
can only reference, as example, even number word addresses, then to have
the compiler correctly cast a char * to a long * would mean it rearranged
your data for you.  In particular, an array of characters would have to
be remade into an array of longs with the apropriate (high or low) byte
holding the character.  Is this all wrong?

But do you *really want* to cast a char pointer to a long pointer just
to dereference and return the value?  The example seems to instead call
for dereferencing the char * and casting the value as a long, e.g.,
		return (long) *cp;
  
I only respond because I'm not certain myself and would like some further
discussion.

Kent Black

friesen@psivax.UUCP (07/10/86)

In article <3783@reed.UUCP> kab@reed.UUCP (Kent Black) writes:
> 
>Oh, am I in over my head. . .
>
>If a (char *) can reference any `byte' of memory, and a (long *) can
>can only reference, as example, even number word addresses, then to have
>the compiler correctly cast a char * to a long * would mean it rearranged
>your data for you.  In particular, an array of characters would have to
>be remade into an array of longs with the apropriate (high or low) byte
>holding the character.  Is this all wrong?

	Yes, the  purpose of the cast is to allow you to look at your
array of char(or whatever) *as if* it were an array of longs. It would
defeat the purpose of the cast if the compiler rearranged the memory
for you!
>
>But do you *really want* to cast a char pointer to a long pointer just
>to dereference and return the value?  The example seems to instead call
>for dereferencing the char * and casting the value as a long, e.g.,
>		return (long) *cp;
>  
	No, this does something completely different. This reads a
single byte from memory, *extends* it to a long and returns the
result. On the other hand 
		return *(long *)cp;

reads a long from memory and returns it. That is it sort of acts like
a union and allows you to look at the same piece of memory as having
different types.
-- 

				Sarima (Stanley Friesen)

UUCP: {ttidca|ihnp4|sdcrdcf|quad1|nrcvax|bellcore|logico}!psivax!friesen
ARPA: ??