[comp.lang.c] Casting pointers

davids@stsci.EDU (David Silberberg) (07/19/90)

Does anyone know if the following cast operation will perform correctly?

main()
{
	SOME_STRUCT_TYPE	*ptr;
	int			num_chars;

	...
	(char *)ptr += num_chars;
	...
}


If the last line above were replaced by

	 ptr = (char *)ptr + num_chars;

it would perform as desired.  Does casting work on an lvalue?

David Silberberg
(davids@stsci.edu)

volpe@underdog.crd.ge.com (Christopher R Volpe) (07/19/90)

In article <1614@ghost.stsci.edu>, davids@stsci.EDU (David Silberberg) writes:
|>If the last line above were replaced by
|>
|>	 ptr = (char *)ptr + num_chars;
|>
|>it would perform as desired.  Does casting work on an lvalue?

I'm not sure if casting on an l-value is specified anywhere. (Never seen it
in K&R.) But it sometimes does bizarre things. Consider the following
code:                     
main()
{ int i;
  float f;

  f=2.0;
  (float) i = f;
  printf("i==%d\n",i);
}

Compiled with Sun C, this program prints:
i==1073741824

Compiled with gcc, it prints
i==2

Chris Volpe

pmk@craycos.com (Peter Klausler) (07/19/90)

volpe@underdog.crd.ge.com (Christopher R Volpe) writes:
> In article <1614@ghost.stsci.edu>, davids@stsci.EDU (David Silberberg) writes:
> |>If the last line above were replaced by
> |>
> |>	 ptr = (char *)ptr + num_chars;
> |>
> |>it would perform as desired.  Does casting work on an lvalue?
> 
> I'm not sure if casting on an l-value is specified anywhere.

Casts NEVER produce lvalues.

Never ever ever ever ever.

Read section 3.3.4 of the standard.

bls@svl.cdc.com (brian scearce) (07/20/90)

volpe@underdog.crd.ge.com (Christopher R Volpe) writes:
>In article <1614@ghost.stsci.edu>, davids@stsci.EDU (David Silberberg) writes:
>|>If the last line above were replaced by
>|>
>|>	 ptr = (char *)ptr + num_chars;
>|>
>|>it would perform as desired.  Does casting work on an lvalue?

>I'm not sure if casting on an l-value is specified anywhere.

Harbison & Steele (section 7.5.1): "Any permissible conversion may
be invoked by a cast expression.  The result is not an lvalue."

>main()
>{ int i;
>  float f;

>  f=2.0;
>  (float) i = f;
   ^^^^^^^^^^^^^ This is not legal C.
>  printf("i==%d\n",i);
>}

>Compiled with Sun C, this program prints: i==1073741824
>Compiled with gcc, it prints: i==2

It shouldn't compile at all.  The mighty CDC C Version 2 prints,
"Operation can only be performed on lvalues", an excellent diagnostic
if I do say so myself :-)

--
Brian Scearce        \ "I tell you Wellington is a bad general, the English are
(not on CDCs behalf)  \ bad soldiers; we will settle the matter by lunch time."
bls@u02.svl.cdc.com    \   -- Napolean Bonaparte, June 18, 1815 (at Waterloo)
shamash.cdc.com!u02!bls \ From _The Experts Speak_, Cerf & Navasky

ark@alice.UUCP (Andrew Koenig) (07/20/90)

In article <1614@ghost.stsci.edu>, davids@stsci.EDU (David Silberberg) writes:

> Does anyone know if the following cast operation will perform correctly?

> 	(char *)ptr += num_chars;

This is not legal C -- the result of a cast is not an lvalue -- so the
`correct' thing to do is to issue a diagnostic message during compilation.
Some implementations do this, others don't.
-- 
				--Andrew Koenig
				  ark@europa.att.com

steve@taumet.com (Stephen Clamage) (07/20/90)

davids@stsci.EDU (David Silberberg) writes:

>Does anyone know if the following cast operation will perform correctly?
>	(char *)ptr += num_chars;

>If the last line above were replaced by
>	 ptr = (char *)ptr + num_chars;
>it would perform as desired.  Does casting work on an lvalue?

According to ANSI C, a cast is an expression, and cannot result in an
lvalue; so the original line violates the standard.  Historically,
many C compilers allowed the first expression as a shorthand for the
(correct) second expression, and many program were written using that
(incorrect) shorthand.  So compiler writers have been forced by
public pressure (speaking from personal experience) to allow the old
incorrect form ("my old compiler accepted this, so your crummy compiler
is no good!").

To avoid writing the left side of the assignment twice (and to continue
to use the += operator), you may also write the expression as
	*(char**)(&ptr) += num_chars;
In this case, there is no improvement in clarity, but if "ptr" and
"num_chars" are complex expressions, this form may be less error-prone.
I won't argue matters of style, only matters of what is guaranteed to
be portable.

-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

steve@taumet.com (Stephen Clamage) (07/20/90)

harkcom@potato.pa.Yokogawa.CO.JP (Alton Harkcom) writes:

>In article <23590@shamash.cdc.com>
>   bls@svl.cdc.com (brian scearce) writes:

> =}It shouldn't compile at all.  The mighty CDC C Version 2 prints,
> =}"Operation can only be performed on lvalues", an excellent diagnostic
>                                       ^^^^^^^
>   Shouldn't that be rvalue?

No.  If the statement is something like:
	(char*)p += i;
the complaint is not about the cast, but about the left side of the
+= operator, which must be an lvalue.  A cast does not result in an
lvalue.  Actually the left side must be a *modifiable* lvalue, and the
error message would be better if it said that.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

harkcom@potato.pa.Yokogawa.CO.JP (Alton Harkcom) (07/21/90)

In article <23590@shamash.cdc.com>
   bls@svl.cdc.com (brian scearce) writes:

 =}It shouldn't compile at all.  The mighty CDC C Version 2 prints,
 =}"Operation can only be performed on lvalues", an excellent diagnostic
                                       ^^^^^^^
   Shouldn't that be rvalue?

--
--harkcom@potato.pa.yokogawa.co.jp