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


Groups > comp.lang.c > #91358

Re: bit value of a negative number

From Ben Bacarisse <ben.usenet@bsb.me.uk>
Newsgroups comp.lang.c
Subject Re: bit value of a negative number
Date 2016-07-30 15:16 +0100
Organization A noiseless patient Spider
Message-ID <8737mrxlbg.fsf@bsb.me.uk> (permalink)
References <159d5df7-d640-40b1-9866-2bb16d7769ee@googlegroups.com> <87a8gzxv8b.fsf@bsb.me.uk> <punning-20160730120244@ram.dialup.fu-berlin.de>

Show all headers | View raw


ram@zedat.fu-berlin.de (Stefan Ram) writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
<snip>
>>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,

It's a good way too.  For some people learning C, the union way might be
more natural.

> so the
>   following program I wrote at this time (15 years ago?) is
>   using pointers:
>
> bitprint.c
>
> #include <stdio.h>  /* putchar  */
> #include <limits.h> /* CHAR_BIT */
>
> #define DUMP(T,w) { const T const v = w; \
>   dump( &v, sizeof( v )); putchar( '\n' ); }

Personally, I'd include a prototype for the dump function in a macro
like this since, without it, the conversion of &v might go wrong.  Of
course you expect DUMP to be used only in places where a prototype for
dump is in scope, but I like to be cautious.

> static void dump( void const * const buffer, int j )
> { char const * const b = buffer; while( j-- )
>   { register char const c = b[ j ]; 
>     for( register int i = CHAR_BIT; i--; )
>     putchar( '0' +( c >> i & 1 )); }}
>
> int main( void ){ DUMP(double,1.0) DUMP(int,1) }
>
> stdout
> 0011111111110000000000000000000000000000000000000000000000000000
> 00000000000000000000000000000001
>
> stdout
> 0000000000000000000000000000000000000000000000001111000000111111
> 00000001000000000000000000000000
>
>   The outputs are shown for two different implementations.
>
>   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' ); }

Or, in >= C99:

  (dump((union { T value; unsigned char buffer[sizeof (T)]}){
        .value = (v) }.buffer, sizeof (T)), putchar('\n'))

and it's syntactically an expression just like a normal function call.

> 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.

I think each member corresponds to the other and the conclusion does
apply.

>   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.

They take unspecified values.  Some people have, I think, mistakenly
taken this to mean the action is always undefined.  I don't think it is,
though it might be in some cases when the result is a trap
representation.

>   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.

Quite.  The standard can't really say without going into all sort of
troublesome detail, but a helpful footnote explains that the intent is
for the natural meaning to prevail:

  "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."

>   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 )

I don't think it's naive.  For complete object types T there is such a
mapping.  This mapping is not a function, though, because a value may
have multiple representations.

>   and its inverse V( T ),

B(T) has no inverse in the usual sense because it is not a function,
but the mapping from representations to values *is* a function, albeit a
partial one.

>   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.
>
>   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.

Yes, it not quite as simple as it may appear because B(T) is a
multi-valued map and V(S) is a partial function.

-- 
Ben.

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


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