Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #28872 > unrolled thread
| Started by | "BartC" <bc@freeuk.com> |
|---|---|
| First post | 2012-12-02 13:23 +0000 |
| Last post | 2012-12-07 16:54 +0000 |
| Articles | 20 on this page of 77 — 21 participants |
Back to article view | Back to comp.lang.c
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 →
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Piotr Kalinowski <pitkali@gmail.com> |
|---|---|
| Date | 2012-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]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2012-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]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2012-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]
| From | Greg Martin <greg@softsprocket.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-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]
| From | Philipp Thomas <kthomas@linux01.gwdg.de> |
|---|---|
| Date | 2012-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-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]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2012-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-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]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2012-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-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]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2012-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2012-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]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2012-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