Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: bit value of a negative number |
| Date | 2016-07-30 14:21 -0700 |
| Organization | A noiseless patient Spider |
| Message-ID | <kfn4m76om89.fsf@x-alumni2.alumni.caltech.edu> (permalink) |
| References | <159d5df7-d640-40b1-9866-2bb16d7769ee@googlegroups.com> <87a8gzxv8b.fsf@bsb.me.uk> <punning-20160730120244@ram.dialup.fu-berlin.de> |
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> [...]
>
>> Often the best way to examine the representation of an object is to
>> treat it as a sequence of unsigned char which you can do with a union.
>> For any complete object type T you can write
>> union { T value; unsigned char byte[sizeof (T)]; } u;
>> and, after setting u.value, you can look at u.byte[0] and upwards to see
>> the bits that make up the value (including any padding bits).
>
> One might say that in C there are attempts to do type
> punning with unions or with pointers. And it seems to me
> that today it is recommended to do it with unions. When I
> read about this in the German C language newsgroup one or
> two decades ago, they still recommended pointers, so the
> following program I wrote at this time (15 years ago?) is
> using pointers: [... program and sample outputs ...]
>
> Now, in 2016, I try to rewrite it to union type punning:
>
> #include <stdio.h> /* putchar */
> #include <limits.h> /* CHAR_BIT */
>
> #define DUMP(T,v) \
> { union { T value; unsigned char buffer[ sizeof( T )]; } u; \
> u.value = v; \
> dump( u.buffer, sizeof( T )); putchar( '\n' ); }
>
> static void dump( unsigned char const * const b, int j )
> { while( j-- )
> { unsigned char const c = b[ j ];
> for( int i = CHAR_BIT; i--; )
> putchar( '0' +( c >> i & 1 )); }}
>
> int main( void ){ DUMP(double,1.0) DUMP(int,1) }
>
> stdout
> 0011111111110000000000000000000000000000000000000000000000000000
> 00000000000000000000000000000001
>
> I think the old recommendation for pointer type punning
> stems from a misunderstanding of a phrase in the standard:
>
> 6.2.6.1p7 in 2016:
>
> >>When a value is stored in a member of an object of
> union type, the bytes of the object representation that
> do not correspond to that member but do correspond to
> other members take unspecified values.<<
>
> It seems that in my program above, there are no bytes that
> correspond to one member but not to the other, so that the
> conclusion of this sentence does not apply.
Right.
> But some people read the sentence quoted above superficially
> and take it to mean that the other members take undefined
> values. Possibly that was the reason they recommended me to
> prefer pointer type punning 15 years ago.
Another possible reason is that C99 didn't make it clear what was
supposed to happen. If you look in N1256 (dated September 2007),
section 6.5.2.3 paragraph 3 has a clarifying footnote:
If the member used to access 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.
However, this footnote does not appear in N1124 (dated May 2005).
So at the time being considered, 15 years ago, it wasn't obvious
what meaning was intended.
> Still, I have not yet read a sentence in the standard that
> says which values the other members /do/ take, when a value
> is stored in one member (assuming - for simplicity that all
> members have the same size). Since this can differ between
> implementations, it might be /unspecified/ too.
The Standard does a poor job of expressing what the semantics
are here. Reading through the notes of various WG14 meetings
(and maybe also some Defect Reports), it is clear that what
was intended has been the same all along - ie, that the bits of
representation are re-interpreted as a representation of the
type of the member being read. The statement in C89/C90 is
a little different from that, but that version of the Standard
did not discuss the notion of /object representation/, so it
didn't really have the right constructs available to be able
to describe it. In any case the footnote in N1256, and still
present in C11, clearly states what semantics are expected,
and ought to suffice for anyone who only wants to know what
the Standard stipulates, and isn't interested in bickering
about the technicalities of how the semantics are expressed.
> Of, course, the naive assumption is that there is a mapping
> from values of a type to bit sequences of the length
> sizeof( T )*CHAR_BIT. When I call this mapping B( T ) and its
> inverse V( T ), then we assume that type punning from type T
> to type S give
>
> V( S )( B( T )( v ))
>
> for a value v of type T. But I am not sure whether the
> C standard actually says that something like this happens
> when doing union type punning.
Based on the footnote, it seems fair to conclude that WG14 would
say that this result is implied by normative text. My own view
is similar to that. IMO this result does follow from how the
Standard describes the semantics of union types, represenatations
of objects, assignment, and lvalue conversion. The description
falls short (IMO) in that it could (and should) be more explicit
about the transformations that occur between abstract values and
object representations. Clearly the Standard expects that these
transformations occur, but doesn't say so in so many words. But
that is a language-lawyer type of quibble. In practical terms
there isn't any question but that this meaning applies.
> In reality the simplicity of this mapping might be
> distorted by trap representations or by being a relation
> instead of a mapping (i.e., by not being 1-to-1). For
> example, it is conceivable that for values of certain
> types the values of some bits of the underlying bit
> representation are ignored.
Right. What happens is implementation-defined, except that some
aspects of the implementation-defined values may be partially
unspecified. If the types involved both have 1-1 and onto
mappings, then the result is completely determined. Similarly,
if the type used for reading has no dependencies on any
unspecified or partially unspecified bits of the type used for
writing, then the result is completely determined (allowing a
"trap representation" to be a possible result). The last case,
where the type used for reading does have dependencies on
unspecified or partially unspecified bits of the type used for
writing, produces a result that is unspecified, or at least
partially unspecified. Of course, these shadings of unspecified
value are not defined in the Standard, so it doesn't have a good
way to talk about the different cases here. That observation may
partly explain why the Standard doesn't describe the semantics of
union member access more explicitly and exactly.
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
bit value of a negative number sinbad <sinbad.sinbad@gmail.com> - 2016-07-30 02:38 -0700
Re: bit value of a negative number Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-07-30 02:50 -0700
Re: bit value of a negative number Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-30 11:42 +0100
Re: bit value of a negative number James Kuyper <jameskuyper@verizon.net> - 2016-07-30 09:38 -0400
Re: bit value of a negative number "James R. Kuyper" <jameskuyper@verizon.net> - 2016-07-30 11:39 -0400
Re: bit value of a negative number Keith Thompson <kst-u@mib.org> - 2016-07-30 13:59 -0700
Re: bit value of a negative number Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-30 15:16 +0100
Re: bit value of a negative number Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-31 06:31 -0700
Re: bit value of a negative number Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-31 17:28 +0100
Re: bit value of a negative number supercat@casperkitty.com - 2016-07-31 13:19 -0700
Re: bit value of a negative number Ike Naar <ike@iceland.freeshell.org> - 2016-07-31 20:46 +0000
Re: bit value of a negative number Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-30 14:21 -0700
Re: bit value of a negative number supercat@casperkitty.com - 2016-07-31 13:37 -0700
Re: bit value of a negative number Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-31 16:59 -0700
Re: bit value of a negative number supercat@casperkitty.com - 2016-07-31 12:56 -0700
Re: bit value of a negative number Barry Schwarz <schwarzb@dqel.com> - 2016-07-30 10:15 -0700
Re: bit value of a negative number Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-30 10:25 -0700
csiph-web