Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #28872 > unrolled thread

Casts on lvalues

Started by"BartC" <bc@freeuk.com>
First post2012-12-02 13:23 +0000
Last post2012-12-07 16:54 +0000
Articles 20 on this page of 77 — 21 participants

Back to article view | Back to comp.lang.c


Contents

  Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-02 13:23 +0000
    Re: Casts on lvalues SG <sgesemann@gmail.invalid> - 2012-12-02 14:40 +0100
    Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-02 13:53 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-06 12:26 +0000
        Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-06 15:15 +0000
        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-06 12:05 -0800
    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-02 12:34 -0800
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-02 21:18 +0000
        Re: Casts on lvalues Willem <willem@turtle.stack.nl> - 2012-12-05 22:36 +0000
          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 23:46 +0000
            Re: Casts on lvalues Willem <willem@turtle.stack.nl> - 2012-12-06 18:35 +0000
      Re: Casts on lvalues pete <pfiland@mindspring.com> - 2012-12-02 16:21 -0500
        Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-02 17:10 -0500
          Re: Casts on lvalues pete <pfiland@mindspring.com> - 2012-12-02 18:50 -0500
        Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-02 19:14 -0500
    Re: Casts on lvalues falk@rahul.net (Edward A. Falk) - 2012-12-04 23:57 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 01:35 +0000
        Re: Casts on lvalues Piotr Kalinowski <pitkali@gmail.com> - 2012-12-05 16:07 +0100
          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 16:47 +0000
            Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-05 13:04 -0500
              Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 18:39 +0000
                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-05 14:23 -0500
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 22:11 +0000
                    Re: Casts on lvalues Ian Collins <ian-news@hotmail.com> - 2012-12-06 11:51 +1300
                      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 23:58 +0000
                        Re: Casts on lvalues Piotr Kalinowski <pitkali@gmail.com> - 2012-12-06 22:00 +0100
                    Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-06 03:05 +0000
                Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-05 14:43 -0500
                Re: Casts on lvalues Greg Martin <greg@softsprocket.com> - 2012-12-05 12:25 -0800
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 21:57 +0000
                    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-05 16:09 -0800
                      Re: Casts on lvalues Philipp Thomas <kthomas@linux01.gwdg.de> - 2012-12-07 01:24 +0100
                        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-06 17:22 -0800
                          Re: Casts on lvalues Öö Tiib <ootiib@hot.ee> - 2012-12-07 00:31 -0800
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 08:18 -0500
                              Re: Casts on lvalues Öö Tiib <ootiib@hot.ee> - 2012-12-07 09:07 -0800
                            Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-07 11:01 -0800
                              Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 21:57 +0000
                                Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-07 22:29 +0000
                                  Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-08 00:04 +0000
                              Re: Casts on lvalues lawrence.jones@siemens.com - 2012-12-15 16:51 -0500
                                Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-15 15:48 -0800
                                  Re: Casts on lvalues lawrence.jones@siemens.com - 2012-12-17 16:37 -0500
                              Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:58 -0800
                            Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:53 -0800
                          Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:43 -0800
                Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-05 22:07 +0000
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 22:20 +0000
                    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-05 16:10 -0800
                    Re: Casts on lvalues Philip Lantz <prl@canterey.us> - 2012-12-06 22:49 -0800
                      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 12:54 +0000
                        Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 08:22 -0500
                          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 13:48 +0000
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 11:17 -0500
                              Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 17:33 +0000
                                Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 18:28 +0000
                                  Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 22:18 +0000
                              Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 18:27 +0000
                                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 14:14 -0500
                                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 20:16 +0000
                                    Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 15:41 -0500
                                      Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 03:03 -0800
                Re: Casts on lvalues Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2012-12-09 17:54 +0200
                  Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-09 12:38 -0500
                    Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-09 18:50 +0000
                      Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-09 14:31 -0500
                        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-09 20:12 -0800
                          Re: Casts on lvalues Heikki Kallasjoki <fis+usenet@zem.fi> - 2012-12-10 07:38 +0000
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 08:12 -0500
                              Re: Casts on lvalues Heikki Kallasjoki <fis+usenet@zem.fi> - 2012-12-10 17:46 +0000
                                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 12:59 -0500
                                Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-10 12:07 -0800
                              Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 03:11 -0800
                          Re: Casts on lvalues Ian Collins <ian-news@hotmail.com> - 2012-12-10 20:50 +1300
                          Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 07:49 -0500
    Re: Casts on lvalues Rui Maciel <rui.maciel@gmail.com> - 2012-12-07 15:19 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 16:54 +0000

Page 2 of 4 — ← Prev page 1 [2] 3 4  Next page →


#28951

From"BartC" <bc@freeuk.com>
Date2012-12-05 18:39 +0000
Message-ID<KBMvs.279623$kt5.191450@fx08.am4>
In reply to#28950

"Eric Sosman" <esosman@comcast-dot-net.invalid> wrote in message 
news:k9o2b3$bcb$1@dont-email.me...
> On 12/5/2012 11:47 AM, BartC wrote:
>>
>> Yet, C allows to you to do this - cast the target of a pointer - in an
>> rvalue expression.
>
>     No: C allows you to apply a cast operator to a *value* (which
> may have been extracted from a pointer's target), not to the target
> itself.

Take this example:

typedef unsigned char byte;

int a = 0x12345678;
int* p = &a;

printf( "*p = %X\n", *p);
printf( "*p = %X\n", *(byte*)p);

In the last line, p is made to behave as though it was a byte pointer, 
rather than an int pointer. And quite likely, a byte value is requested from 
memory rather than an int one. Also, in most cases, the value of the pointer 
need not be changed.

The effect is to change the target of the pointer *type*, rather than any 
actual value.

>>[...]
>> I asked about doing the same on the left side of an assignment.
>>
>> It's this asymmetry that is the issue.
>
>     Um, er, assignment itself is asymmetric ...

Plenty of terms can appear interchangeably on both left and right sides.

But while A can appear on either side, (T)A can't. And there doesn't appear 
to be a convincing reason why not.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28952

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-12-05 14:23 -0500
Message-ID<50BF9F15.7060608@verizon.net>
In reply to#28951
On 12/05/2012 01:39 PM, BartC wrote:
...
>> On 12/5/2012 11:47 AM, BartC wrote:
...
>>> I asked about doing the same on the left side of an assignment.
...
> But while A can appear on either side, (T)A can't. And there doesn't appear 
> to be a convincing reason why not.

The reason is the same as the one that Keith gave to the similar
question you asked at the start of this thread about compound assignment
expressions: "The result of a cast is not an lvalue." Since it's not an
lvalue, no memory is set aside to store anything in it. It appears that
you want

	(T)A op= B

to have the meaning that can currently be expressed in standard C as

	A = (T)A op B.

but it's not clear to me what you want

       (T)A = B

to mean. Can you express it in terms of standard C, the way that I did
above for op=? Consider:

    int a=3;
    (double)a = 3.14;

Currently, this is equivalent to

    3.0 = 3.14;

and therefore disallowed for the same reason that 3.0 = 3.14 is. What
would you like it to do in a revised version of C?

[toc] | [prev] | [next] | [standalone]


#28959

From"BartC" <bc@freeuk.com>
Date2012-12-05 22:11 +0000
Message-ID<rFPvs.640122$9D6.94777@fx27.am4>
In reply to#28952
"James Kuyper" <jameskuyper@verizon.net> wrote in message
news:50BF9F15.7060608@verizon.net...
> On 12/05/2012 01:39 PM, BartC wrote:

>> But while A can appear on either side, (T)A can't. And there doesn't
>> appear
>> to be a convincing reason why not.
>
> The reason is the same as the one that Keith gave to the similar
> question you asked at the start of this thread about compound assignment
> expressions: "The result of a cast is not an lvalue."

OK, I get that now. But that's only because the Book says so.

>It appears that you want
>
> (T)A op= B
>
> to have the meaning that can currently be expressed in standard C as
>
> A = (T)A op B.

It's not quite that either, because this might involve unwanted int/float
conversions.

> but it's not clear to me what you want
>
>       (T)A = B
>
> to mean. Can you express it in terms of standard C, the way that I did
> above for op=?

It means: "pretend that A is a variable of type T for this assignment".

> Consider:
>
>    int a=3;
>    (double)a = 3.14;
>
> Currently, this is equivalent to
>
>    3.0 = 3.14;
>
> and therefore disallowed for the same reason that 3.0 = 3.14 is. What
> would you like it to do in a revised version of C?

Well in this case it wouldn't do anything too useful! But turning it around
a little:

double a;

(int)a = 3142;

This just writes the bit-pattern for integer 3142 in (on my machine) the
bottom half of a. But that, I can currently do in C using instead:

*(int*)&a = 3142;

(even though people don't seem to like this either). My original example was
more like this:

int* P;

++(char*)P;

ie. treat P as as a char* pointer (so that on my machine, the value in P
increments by 1 instead of 4).

I used to do this stuff in another language something like this:

double a;
int n;
equivalence(a,n)   /* a and n share the same memory location */

n=3142;   /* does what I tried to do above */

OK, I understand in C, you have to use unions and memcpys and things. But
that's not always straightforward (for example, 'a' might be an extern 
variable, or part of an array).


-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28962

FromIan Collins <ian-news@hotmail.com>
Date2012-12-06 11:51 +1300
Message-ID<aia1eqF5qfmU2@mid.individual.net>
In reply to#28959
BartC wrote:
>
> My original example was
> more like this:
>
> int* P;
>
> ++(char*)P;
>
> ie. treat P as as a char* pointer (so that on my machine, the value in P
> increments by 1 instead of 4).

Which may well result in P not being a valid pointer to an int, ending 
the world when it is dereferenced.  Such a construct is like giving a 3 
year old a box ox matches.  C does have plenty of matches on offer, but 
they are normally in child proof boxes.

If you want a pointer to walk through some data built from an arbitrary 
set of types, use a char*.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#28964

From"BartC" <bc@freeuk.com>
Date2012-12-05 23:58 +0000
Message-ID<3dRvs.786837$A%.348239@fx26.am4>
In reply to#28962

"Ian Collins" <ian-news@hotmail.com> wrote in message 
news:aia1eqF5qfmU2@mid.individual.net...
> BartC wrote:
>>
>> My original example was
>> more like this:
>>
>> int* P;
>>
>> ++(char*)P;
>>
>> ie. treat P as as a char* pointer (so that on my machine, the value in P
>> increments by 1 instead of 4).
>
> Which may well result in P not being a valid pointer to an int, ending the 
> world when it is dereferenced.  Such a construct is like giving a 3 year 
> old a box ox matches.  C does have plenty of matches on offer, but they 
> are normally in child proof boxes.

But, I can do the equivalent of ++(char*)P by writing:

 P = (int*)((char*)P+1);

(or near enough if that's not quite right.) So the world can still end.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28997

FromPiotr Kalinowski <pitkali@gmail.com>
Date2012-12-06 22:00 +0100
Message-ID<m2boe6q4jg.fsf@h-104-37.a155.priv.bahnhof.se>
In reply to#28964
"BartC" <bc@freeuk.com> writes:

> "Ian Collins" <ian-news@hotmail.com> wrote in message
> news:aia1eqF5qfmU2@mid.individual.net...
> But, I can do the equivalent of ++(char*)P by writing:
>
> P = (int*)((char*)P+1);
>
> (or near enough if that's not quite right.) So the world can still end.

It's not about disallowing you to shoot yourself. It's about making it
more difficult, so you're slightly less likely to do it. It's about
increasing the cost of ending the world, so that you'll think twice
(hopefully) before doing it.

Regards,
Piotr Kalinowski

[toc] | [prev] | [next] | [standalone]


#28967

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2012-12-06 03:05 +0000
Message-ID<k9p224$c3p$1@speranza.aioe.org>
In reply to#28959
BartC <bc@freeuk.com> wrote:
> "James Kuyper" <jameskuyper@verizon.net> wrote in message
> news:50BF9F15.7060608@verizon.net...
>> On 12/05/2012 01:39 PM, BartC wrote:
 
>>> But while A can appear on either side, (T)A can't. And there doesn't
>>> appear
>>> to be a convincing reason why not.

>> The reason is the same as the one that Keith gave to the similar
>> question you asked at the start of this thread about compound assignment
>> expressions: "The result of a cast is not an lvalue."
 
> OK, I get that now. But that's only because the Book says so.
 
(snip)

> It's not quite that either, because this might involve unwanted int/float
> conversions.
 
(snip)

> It means: "pretend that A is a variable of type T for this assignment".

(snip)
> Well in this case it wouldn't do anything too useful! But turning it around
> a little:
 
> double a;
 
> (int)a = 3142;
 
> This just writes the bit-pattern for integer 3142 in (on my machine) the
> bottom half of a. But that, I can currently do in C using instead:

OK, but now that C has complex variables:

In PL/I, you can use the functions REAL and IMAG to get the
real and imaginary parts of a complex expression, and COMPLEX to
get a complex value from two real expressions.

PL/I uses functions where C would use casts, so to get the fixed
point value from a floating point expression you use the function 
FIXED. 

In addition to the functions REAL, IMAG, and COMPLEX, there are also
pseudo-variables, which allow for statements like:

    REAL(Z)=3;

which assigns 3 to the real part of Z, leaving the imaginary part
unchanged. You can even do:

   DCL Z FIXED BIN(31,0) COMPLEX;
   Z=0;
   DO IMAG(Z)=1 TO 100 BY 3;
      PUT SKIP LIST(Z,SQRT(Z));
   END;

in which case IMAG is both a function and pseudo-variable.
(It also works with FLOAT variables.)

Other pseudo-variables are SUBSTR and UNSPEC.

-- glen

[toc] | [prev] | [next] | [standalone]


#28953

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2012-12-05 14:43 -0500
Message-ID<k9o85i$f4u$1@dont-email.me>
In reply to#28951
On 12/5/2012 1:39 PM, BartC wrote:
>
>
> "Eric Sosman" <esosman@comcast-dot-net.invalid> wrote in message
> news:k9o2b3$bcb$1@dont-email.me...
>> On 12/5/2012 11:47 AM, BartC wrote:
>>>
>>> Yet, C allows to you to do this - cast the target of a pointer - in an
>>> rvalue expression.
>>
>>     No: C allows you to apply a cast operator to a *value* (which
>> may have been extracted from a pointer's target), not to the target
>> itself.
>
> Take this example:
>
> typedef unsigned char byte;
>
> int a = 0x12345678;
> int* p = &a;
>
> printf( "*p = %X\n", *p);
> printf( "*p = %X\n", *(byte*)p);
>
> In the last line, p is made to behave as though it was a byte pointer,
> rather than an int pointer. And quite likely, a byte value is requested
> from memory rather than an int one. Also, in most cases, the value of
> the pointer need not be changed.

     No: `p' is not "made to behave" like anything other than
what it is.  `p' is an identifier, which (in this context) is
seen first as a primary expression (6.5.1p2), and then as an
lvalue (6.3.2.1p1).  The object designated by this lvalue is
consulted to obtain a value (6.3.2.1p2); this value points at
the object designated by `a' and has the type `int*'.

     The `(byte*)' operator converts the extracted value to the
`(unsigned char*)' type (6.5.4), and this converted value points
at the lowest-addressed constituent byte of the object designated
by `a' (6.3.2.3p7).

     The `*' operator uses the `(unsigned char*)' value produced
by the cast to designate the pointed-to byte (6.5.3.2p4), and
this designation is an lvalue (6.3.2.1p1 again), from which is
extracted the value stored in the designated byte (6.3.2.1p2
again), which is a value of type `unsigned char'.  The default
argument promotions convert this value to `int' or `unsigned int',
and lo! we've computed an argument for printf().

     `p' is unchanged throughout all of this.  Its value has not
changed, its behavior has not changed, its nature has not changed.
It has not put on makeup, adopted a foreign accent, or affected a
silly walk.  It is still an `int*' aimed at the object designated
by `a'.

> The effect is to change the target of the pointer *type*, rather than
> any actual value.

     No.  See above -- or ask "Has the type of `p's target changed?"
Since `p's target is exactly what it was to begin with, and has made
no sorties into strange territory and back again, the answer is "No."
There has been no change, hence "the effect is to change" is wrong.

>>> [...]
>>> I asked about doing the same on the left side of an assignment.
>>>
>>> It's this asymmetry that is the issue.
>>
>>     Um, er, assignment itself is asymmetric ...
>
> Plenty of terms can appear interchangeably on both left and right sides.
>
> But while A can appear on either side, (T)A can't. And there doesn't
> appear to be a convincing reason why not.

     If you're not convinced that an lvalue is different from other
kinds of expressions, you're beyond my power to educate -- but that's
nothing new.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#28954

FromGreg Martin <greg@softsprocket.com>
Date2012-12-05 12:25 -0800
Message-ID<U4Ovs.586$ww5.519@newsfe01.iad>
In reply to#28951
On 12-12-05 10:39 AM, BartC wrote:
>
>
> "Eric Sosman" <esosman@comcast-dot-net.invalid> wrote in message
> news:k9o2b3$bcb$1@dont-email.me...
>> On 12/5/2012 11:47 AM, BartC wrote:
>>>
>>> Yet, C allows to you to do this - cast the target of a pointer - in an
>>> rvalue expression.
>>
>>     No: C allows you to apply a cast operator to a *value* (which
>> may have been extracted from a pointer's target), not to the target
>> itself.
>
> Take this example:
>
> typedef unsigned char byte;
>
> int a = 0x12345678;
> int* p = &a;
>
> printf( "*p = %X\n", *p);
> printf( "*p = %X\n", *(byte*)p);
>
> In the last line, p is made to behave as though it was a byte pointer,
> rather than an int pointer. And quite likely, a byte value is requested
> from memory rather than an int one. Also, in most cases, the value of
> the pointer need not be changed.
>
> The effect is to change the target of the pointer *type*, rather than
> any actual value.
>
>>> [...]
>>> I asked about doing the same on the left side of an assignment.
>>>
>>> It's this asymmetry that is the issue.
>>
>>     Um, er, assignment itself is asymmetric ...
>
> Plenty of terms can appear interchangeably on both left and right sides.
>
> But while A can appear on either side, (T)A can't. And there doesn't
> appear to be a convincing reason why not.
>

Since you aren't actually changing A by (T)A but rather saying treat 
it's value like it's a T rather then A's declared type, it doesn't 
really make sense. I can't see the value of momentarily treating A like 
it's a T just to fool the compiler. Presuming T is larger then A are you 
asking the compiler to overwrite the memory adjacent to A? Probably not. 
Your probably asking it to cast the value to A's type which is more 
logically written A = (A_Type) some_T; // IMO.

Excuse me if I've missed your meaning but I think if you think about 
what a cast is you'll see it doesn't apply to lvalues.




[toc] | [prev] | [next] | [standalone]


#28958

From"BartC" <bc@freeuk.com>
Date2012-12-05 21:57 +0000
Message-ID<qFPvs.640121$9D6.90678@fx27.am4>
In reply to#28954
"Greg Martin" <greg@softsprocket.com> wrote in message 
news:U4Ovs.586$ww5.519@newsfe01.iad...
> On 12-12-05 10:39 AM, BartC wrote:

>> Plenty of terms can appear interchangeably on both left and right sides.
>>
>> But while A can appear on either side, (T)A can't. And there doesn't
>> appear to be a convincing reason why not.
>>
>
> Since you aren't actually changing A by (T)A but rather saying treat it's 
> value like it's a T rather then A's declared type, it doesn't really make 
> sense.

Isn't that the point of having casts?

> I can't see the value of momentarily treating A like it's a T just to fool 
> the compiler.

On a platform that you know inside-out, and where the alternative is to do 
exactly the same but using assembly code with all of it's disadvantages, 
there there is plenty of value in doing it.

When you have a datablock of mixed-type data, and traversing it via a 
pointer, then you might expect to switch pointer types all the time, rather 
than messing with unions and memcpys.

> Presuming T is larger then A are you asking the compiler to overwrite the 
> memory adjacent to A? Probably not.

Yes. But you'd be sensible enough not to do that.

> Your probably asking it to cast the value to A's type which is more 
> logically written A = (A_Type) some_T; // IMO.

That's not quite the same. See the example I gave in my reply to James.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28965

FromKeith Thompson <kst-u@mib.org>
Date2012-12-05 16:09 -0800
Message-ID<ln1uf4qbws.fsf@nuthaus.mib.org>
In reply to#28958
"BartC" <bc@freeuk.com> writes:
> "Greg Martin" <greg@softsprocket.com> wrote in message 
> news:U4Ovs.586$ww5.519@newsfe01.iad...
>> On 12-12-05 10:39 AM, BartC wrote:
>>> Plenty of terms can appear interchangeably on both left and right sides.
>>>
>>> But while A can appear on either side, (T)A can't. And there doesn't
>>> appear to be a convincing reason why not.
>>
>> Since you aren't actually changing A by (T)A but rather saying treat it's 
>> value like it's a T rather then A's declared type, it doesn't really make 
>> sense.
>
> Isn't that the point of having casts?

No.  The point of a cast is to explicitly convert a *value* of some
type to a value of some other specified type.

There are several ways in C to treat an object of some type as if it
were an object of some other type.  A simple cast is not one of them.

Depending on what you're trying to do, you can take the object's
address, cast it to some other pointer type, and then dereference the
result.  You do so at your own risk; it can fail badly if the object
doesn't have the proper alignment for the target type, or if the target
type is larger than the object, or if you assign an invalid value (such
as a trap representation) to the object.

Or you can use a union; this avoids alignment issues, but the other
problems still apply.

Or you can use memcpy() to create a *copy* of an object's representation
in an object of a different type.

>> I can't see the value of momentarily treating A like it's a T just to fool 
>> the compiler.
>
> On a platform that you know inside-out, and where the alternative is to do 
> exactly the same but using assembly code with all of it's disadvantages, 
> there there is plenty of value in doing it.

There are *plenty* of ways to do what you want to do without
resorting to assembly code.  It's true that they're not as
syntactically "clean" as a hypothetical lvalue cast.  Personally,
I think that's a good thing; type-punning is dangerous enough that
it shouldn't be done casually.  If you think it should be easier
to do, that's fine.  I don't think *anyone* is 100% happy with the
way C is defined.

I suppose you could define a macros to make it easier:

#include <stdio.h>

#define PUN(object, type) (*(type*)&(object))

int main(void) {
    unsigned u;
    PUN(u, float) = 1.0/3.0;
    printf("u (as float) = %g\n", PUN(u, float));
    printf("u = 0x%x\n", u);
    return 0;
}

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#29003

FromPhilipp Thomas <kthomas@linux01.gwdg.de>
Date2012-12-07 01:24 +0100
Message-ID<4ld2c8d9mskkhqrfab8d9n9k8jv2b4p7i6@4ax.com>
In reply to#28965
On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
wrote:

>Or you can use a union; this avoids alignment issues, but the other
>problems still apply.

When used for type-punning that isn't guaranteed to work but depends
on the compiler.

>Or you can use memcpy() to create a *copy* of an object's representation
>in an object of a different type.

And this is the only clean way to fix type-punning and avoid alignment
issues.

Philipp

[toc] | [prev] | [next] | [standalone]


#29004

FromKeith Thompson <kst-u@mib.org>
Date2012-12-06 17:22 -0800
Message-ID<lnboe6psew.fsf@nuthaus.mib.org>
In reply to#29003
Philipp Thomas <kthomas@linux01.gwdg.de> writes:
> On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
> wrote:
>>Or you can use a union; this avoids alignment issues, but the other
>>problems still apply.
>
> When used for type-punning that isn't guaranteed to work but depends
> on the compiler.

A footnote in the standard (N1370 6.5.2.3p3, footnote 95) says:

    If the member used to read the contents of a union object is
    not the same as the member last used to store a value in the
    object, the appropriate part of the object representation of
    the value is reinterpreted as an object representation in the
    new type as described in 6.2.6 (a process sometimes called
    "type punning"). This might be a trap representation.

I'm not sure why that's stated only in a non-normative footnote.
I suppose the implication is that it's already stated normatively,
but it's not clear to me that it is.

In any case, a union does avoid alignment issues.

>>Or you can use memcpy() to create a *copy* of an object's representation
>>in an object of a different type.
>
> And this is the only clean way to fix type-punning and avoid alignment
> issues.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#29010

FromÖö Tiib <ootiib@hot.ee>
Date2012-12-07 00:31 -0800
Message-ID<7216db87-28bd-41a0-9fd9-6a0fe23158d5@googlegroups.com>
In reply to#29004
On Friday, 7 December 2012 03:22:47 UTC+2, Keith Thompson  wrote:
> Philipp Thomas <kthomas@linux01.gwdg.de> writes:
> > On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
> > wrote:
> >>Or you can use a union; this avoids alignment issues, but the other
> >>problems still apply.
> >
> > When used for type-punning that isn't guaranteed to work but depends
> > on the compiler.
> 
> A footnote in the standard (N1370 6.5.2.3p3, footnote 95) says:
> 
>     If the member used to read the contents of a union object is
>     not the same as the member last used to store a value in the
>     object, the appropriate part of the object representation of
>     the value is reinterpreted as an object representation in the
>     new type as described in 6.2.6 (a process sometimes called
>     "type punning"). This might be a trap representation.
> 
> I'm not sure why that's stated only in a non-normative footnote.
> I suppose the implication is that it's already stated normatively,
> but it's not clear to me that it is.

C99 has such texts:

    6.2.5p20, union has an overlapping set of member objects
    6.7.2.1p14, the value of at most one of the members can be stored in a union object at any time
    Annex J.1 the value of a union member other than the last one stored into is unspecified.

I do not feel it safe to use union for type punning.

[toc] | [prev] | [next] | [standalone]


#29017

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-12-07 08:18 -0500
Message-ID<k9sqba$ch3$1@dont-email.me>
In reply to#29010
On 12/07/2012 03:31 AM, � wrote:
> On Friday, 7 December 2012 03:22:47 UTC+2, Keith Thompson  wrote:
>> Philipp Thomas <kthomas@linux01.gwdg.de> writes:
>>> On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
>>> wrote:
>>>> Or you can use a union; this avoids alignment issues, but the other
>>>> problems still apply.
>>>
>>> When used for type-punning that isn't guaranteed to work but depends
>>> on the compiler.
>>
>> A footnote in the standard (N1370 6.5.2.3p3, footnote 95) says:
>>
>>     If the member used to read the contents of a union object is
>>     not the same as the member last used to store a value in the
>>     object, the appropriate part of the object representation of
>>     the value is reinterpreted as an object representation in the
>>     new type as described in 6.2.6 (a process sometimes called
>>     "type punning"). This might be a trap representation.
>>
>> I'm not sure why that's stated only in a non-normative footnote.
>> I suppose the implication is that it's already stated normatively,
>> but it's not clear to me that it is.
> 
> C99 has such texts:
> 
>     6.2.5p20, union has an overlapping set of member objects
>     6.7.2.1p14, the value of at most one of the members can be stored in a union object at any time
>     Annex J.1 the value of a union member other than the last one stored into is unspecified.
> 
> I do not feel it safe to use union for type punning.

Keep in mind that footnote 95 merely describes what the committee
intended to be the case from the very beginning, and what is easiest to
implement, and what virtually every real implementation of C always has
implemented, because a great many C programmers have always assumed it
was true. It's not really worthwhile worrying about the possibility that
a union won't work as described by footnote 95. There's much better
things to worry about - such as the fact that type punning inherently
requires building into your code implementation-specific knowledge about
how the two types are represented.


-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#29026

FromÖö Tiib <ootiib@hot.ee>
Date2012-12-07 09:07 -0800
Message-ID<91e1c148-0da2-4d1a-b707-9b8bcb86f55e@googlegroups.com>
In reply to#29017
On Friday, 7 December 2012 15:18:33 UTC+2, James Kuyper  wrote:
> On 12/07/2012 03:31 AM, � wrote:
> > On Friday, 7 December 2012 03:22:47 UTC+2, Keith Thompson  wrote:
> >> Philipp Thomas <kthomas@linux01.gwdg.de> writes:
> >>> On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
> >>> wrote:
> >>>> Or you can use a union; this avoids alignment issues, but the other
> >>>> problems still apply.
> >>>
> >>> When used for type-punning that isn't guaranteed to work but depends
> >>> on the compiler.
> >>
> >> A footnote in the standard (N1370 6.5.2.3p3, footnote 95) says:
> >>
> >>     If the member used to read the contents of a union object is
> >>     not the same as the member last used to store a value in the
> >>     object, the appropriate part of the object representation of
> >>     the value is reinterpreted as an object representation in the
> >>     new type as described in 6.2.6 (a process sometimes called
> >>     "type punning"). This might be a trap representation.
> >>
> >> I'm not sure why that's stated only in a non-normative footnote.
> >> I suppose the implication is that it's already stated normatively,
> >> but it's not clear to me that it is.
> > 
> > C99 has such texts:
> > 
> >     6.2.5p20, union has an overlapping set of member objects
> >     6.7.2.1p14, the value of at most one of the members can be stored in a union object at any time
> >     Annex J.1 the value of a union member other than the last one stored into is unspecified.
> > 
> > I do not feel it safe to use union for type punning.
> 
> Keep in mind that footnote 95 merely describes what the committee
> intended to be the case from the very beginning, and what is easiest to
> implement, and what virtually every real implementation of C always has
> implemented, because a great many C programmers have always assumed it
> was true.

Yes, I am not worried how union is implemented, I am worried if an 
optimizer might ignore that footnote and optimize too lot in some
case. So ... I prefer to memcpy or to cast (properly aligned) pointers.

> It's not really worthwhile worrying about the possibility that
> a union won't work as described by footnote 95. There's much better
> things to worry about - such as the fact that type punning inherently
> requires building into your code implementation-specific knowledge about
> how the two types are represented.

[toc] | [prev] | [next] | [standalone]


#29037

FromKeith Thompson <kst-u@mib.org>
Date2012-12-07 11:01 -0800
Message-ID<ln7gotptyq.fsf@nuthaus.mib.org>
In reply to#29010
Öö Tiib <ootiib@hot.ee> writes:
> On Friday, 7 December 2012 03:22:47 UTC+2, Keith Thompson  wrote:
>> Philipp Thomas <kthomas@linux01.gwdg.de> writes:
>> > On Wed, 05 Dec 2012 16:09:23 -0800, Keith Thompson <kst-u@mib.org>
>> > wrote:
>> >>Or you can use a union; this avoids alignment issues, but the other
>> >>problems still apply.
>> >
>> > When used for type-punning that isn't guaranteed to work but depends
>> > on the compiler.
>> 
>> A footnote in the standard (N1370 6.5.2.3p3, footnote 95) says:
>> 
>>     If the member used to read the contents of a union object is
>>     not the same as the member last used to store a value in the
>>     object, the appropriate part of the object representation of
>>     the value is reinterpreted as an object representation in the
>>     new type as described in 6.2.6 (a process sometimes called
>>     "type punning"). This might be a trap representation.
>> 
>> I'm not sure why that's stated only in a non-normative footnote.
>> I suppose the implication is that it's already stated normatively,
>> but it's not clear to me that it is.
>
> C99 has such texts:
>
>     6.2.5p20, union has an overlapping set of member objects
>     6.7.2.1p14, the value of at most one of the members can be stored
>     in a union object at any time
>     Annex J.1 the value of a union member other than the last one
>     stored into is unspecified.
>
> I do not feel it safe to use union for type punning.

Note that C99 doesn't have that footnote, but N1256 does.  It was added
by one of Technical Corrigenda 3 -- but N1256 (which incorporates TC3)
still has that clause in Annex J.1.  I suspect this is just an
oversight.

N1570 (essentially C2011) changed the wording of the clause in J.1
(which is a list of unspecified behaviors) from:
    The value of a union member other than the last one stored into
    (6.2.6.1)
to:
    The values of bytes that correspond to union members other than the
    one last stored into (6.2.6.1).

I can't find the list of C99 DRs (the link I had,
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm>
now points to the list of C2011 DRs), so I don't know which DR
introduced this change.

But the implication is that the committee felt that the existing C99
standard already implied what the footnote says.  It's conceivable
that a compiler could behave differently, (e.g., by optimizing away
an assignment to a union member if that member is never access again)
-- but such a compiler would break a good deal of existing code that
depends on this behavior, whether it's guaranteed by the standard
or not.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#29047

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2012-12-07 21:57 +0000
Message-ID<k9tone$6ca$1@speranza.aioe.org>
In reply to#29037
Keith Thompson <kst-u@mib.org> wrote:

(snip, someone wrote)
>> I do not feel it safe to use union for type punning.
 
> Note that C99 doesn't have that footnote, but N1256 does.  It was added
> by one of Technical Corrigenda 3 -- but N1256 (which incorporates TC3)
> still has that clause in Annex J.1.  I suspect this is just an
> oversight.
 
(snip)

> But the implication is that the committee felt that the existing C99
> standard already implied what the footnote says.  It's conceivable
> that a compiler could behave differently, (e.g., by optimizing away
> an assignment to a union member if that member is never access again)
> -- but such a compiler would break a good deal of existing code that
> depends on this behavior, whether it's guaranteed by the standard
> or not.

Some time ago, I was trying to figure out if it would be
possible for a C compiler to generate JVM code.

JVM has no operation that stores different types in the same memory.
I believe it isn't so hard to make a memcpy() that can do the
appropriate conversions and copies, though.

It seemed to me at the time that implementing union the same as
struct was one way that would work, and would also follow the 
standard. (Though maybe less memory efficient.)

I asked here at the time, and many seemed to agree, though as you
say, it might break existing code.

-- glen

[toc] | [prev] | [next] | [standalone]


#29050

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-12-07 22:29 +0000
Message-ID<0.282d4b9e5dee28d06a1d.20121207222942GMT.87d2ylo5rd.fsf@bsb.me.uk>
In reply to#29047
glen herrmannsfeldt <gah@ugcs.caltech.edu> writes:

> Keith Thompson <kst-u@mib.org> wrote:
>
> (snip, someone wrote)
>>> I do not feel it safe to use union for type punning.
>  
>> Note that C99 doesn't have that footnote, but N1256 does.  It was added
>> by one of Technical Corrigenda 3 -- but N1256 (which incorporates TC3)
>> still has that clause in Annex J.1.  I suspect this is just an
>> oversight.
>  
> (snip)
>
>> But the implication is that the committee felt that the existing C99
>> standard already implied what the footnote says.  It's conceivable
>> that a compiler could behave differently, (e.g., by optimizing away
>> an assignment to a union member if that member is never access again)
>> -- but such a compiler would break a good deal of existing code that
>> depends on this behavior, whether it's guaranteed by the standard
>> or not.
>
> Some time ago, I was trying to figure out if it would be
> possible for a C compiler to generate JVM code.
>
> JVM has no operation that stores different types in the same memory.
> I believe it isn't so hard to make a memcpy() that can do the
> appropriate conversions and copies, though.
>
> It seemed to me at the time that implementing union the same as
> struct was one way that would work, and would also follow the 
> standard. (Though maybe less memory efficient.)
>
> I asked here at the time, and many seemed to agree, though as you
> say, it might break existing code.

I don't think that would work out.  In particular, 6.5.8 p5 says "All
pointers to members of the same union object compare equal".  Since you
are talking about a compiler here, that alone is not the end of the
matter because the compiler might be able to arrange for this to appear
to be true.  For example, a pointer might be made to consist of two
parts, one that is used for comparison while the other part is an offset
used for union access, but I fear that this won't fly in the long run.
(For example, this particular ruse will go wrong implementing the
special provision for "common initial sequences" in 6.5.2.3 p5.  Again,
a fix-up is possible but I am sceptical about far this can go on.)

It would be an interesting exercise to see if would work, but I'm not
hopeful.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#29053

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2012-12-08 00:04 +0000
Message-ID<k9u06f$odh$1@speranza.aioe.org>
In reply to#29050
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
 
(snip, I wrote)
>> Some time ago, I was trying to figure out if it would be
>> possible for a C compiler to generate JVM code.

>> JVM has no operation that stores different types in the same memory.
>> I believe it isn't so hard to make a memcpy() that can do the
>> appropriate conversions and copies, though.

>> It seemed to me at the time that implementing union the same as
>> struct was one way that would work, and would also follow the 
>> standard. (Though maybe less memory efficient.)

>> I asked here at the time, and many seemed to agree, though as you
>> say, it might break existing code.
 
> I don't think that would work out.  In particular, 6.5.8 p5 says "All
> pointers to members of the same union object compare equal".  Since you
> are talking about a compiler here, that alone is not the end of the
> matter because the compiler might be able to arrange for this to appear
> to be true.  For example, a pointer might be made to consist of two
> parts, one that is used for comparison while the other part is an offset
> used for union access, 

Well, most pointers have to have an Object reference to an array 
and an offset into the array. Any scalar that can be pointed to 
has to instead be an array of length 1.

> but I fear that this won't fly in the long run.
> (For example, this particular ruse will go wrong implementing the
> special provision for "common initial sequences" in 6.5.2.3 p5.  Again,
> a fix-up is possible but I am sceptical about far this can go on.)

As well as I know, all that fun stuff only has to happen for
(unsigned char *), or (void *), so the compiler only has to do that
extra stuff when those occur.

But yes, getting that one right will be tricky.
 
> It would be an interesting exercise to see if would work, but I'm not
> hopeful.

It already gets tricky for struct. If you make a struct a Java class,
then you can have an object reference to the (instance of the) class, 
which is different from a reference to a class member. So, extra
work to get that right.

-- glen

[toc] | [prev] | [next] | [standalone]


Page 2 of 4 — ← Prev page 1 [2] 3 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web