COMPGROUPS.NET | Search | Post Question | Groups | Stream | About | Register

### hex and octal constants in various languages

• Email
• Follow

```I am collecting a sort of phrase books with equivalent "things" in
various languages.

I am now considering the indication of constants as hex, oct or binary
constants. I have considered fortran, C, Java, IDL and (my)sql. I have a
question on the first three.

As a reference I started in Fortran with cases like these (I did also
byte, short and 64bit integers, not shown) :

integer j
j=somevalue
write(*,3)j,j,j,j
3      format(I11.10,1X,B32.32,1X,O11.11,1X,Z8.8)

real r
r=somevalue
write(*,4)r,r,r,r
4      format(G13.7 ,1X,B32.32,1X,O11.11,1X,Z8.8)

character*4 s
equivalence (j,s)
s=somestring
write(*,5)s,s,s,s
5      format(A4    ,1X,B32.32,1X,O11.11,1X,Z8.8)

I tried first with some explicit values (1, -1, 32767, 1.0, 2.0,
huge(0.0), tiny(0.0), "ABCD") and obtained perfectly meaningful binary,
oct and hex values. Then I replaced the assignment using bin, oct or hex
constants

j=z'7FFE'                               ! gives 32866
j=o'37777777776'                        ! give  -2
j=b'11111111111111111111111111111110'
r=z'80800000'                           ! gives tiny
j=z'44434241'                           ! gives "ABCD"

Everything works perfectly. I can assign directly a binary
representation to an integer and to a real, and I can even assign it to
a string if this is in equivalence with an appropriate integer.

I then moved to C, I tried statements like

short i ;
i=somevalue;
printf("%6.5d %6.6o %4.4X %d \n",i,i,i,sizeof(i)) ;

int j ;
j=somevalue ;
printf("%11.10d %11.11o %8.8X %d \n",j,j,j,sizeof(j)) ;

float f ;
f=somevalue ;
printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;

Here I find two problems, a minor and a major one

The minor one is that a positive short is displayed OK
But a negative short is displayed with too many oct and hex digits
i=32767 ;        /*  32767      077777     7FFF */
i=-1;            /* -00001 37777777777 FFFFFFFF */

although a sizeof says that i is 2 bytes

The major problem is that an assignment to a float gives an
unexpected result (no compile or runtime error)

f=0X40800000;  /* should return 4.0  */
f=0X80800000;  /* should return tiny */

For instance the latter returns 2.155872e+09, the former 2.155872e+09
and BOTH THE SAME 00000000000 as octal and 41E01000 as hex (different
from the one I assigned)

In Java I tried

int i ;
System.out.format("i is: %11d %11o %8x %n", i,i,i);

float f ;
System.out.format("f is: %e          %n", f    );

Here format does not support the o and x descriptors for float argument.

Anyhow I tested assignments for integer and they do work

i=037777777776 ;  /* -2    */
i=0X7FFE ;        /* 32766 */

while assignment for real do not work (as in C)

f=0X3F800000;     /* should be 1.0 */
f=0X40800000;     /* should be 4.0 */
f=0X80800000;     /* should by tiny */

(the compiler does not complain, there are no runtime exceptions, but
the result is not what expected

for instance the latter returns -2.139095e+09 and the one for 4.0
returns 1.082130e+09

I haven't tested assignment of hex or oct constants to strings in
neither of the two latter languages (I guess Java will be using unicode,
not plain ascii)

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/15/2009 3:48:42 PM

See related articles to this posting

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

> Then I replaced the assignment using bin, oct or hex  constants
>
>         j=z'7FFE'                               ! gives 32866
>         j=o'37777777776'                        ! give  -2
>         j=b'11111111111111111111111111111110'
>         r=z'80800000'                           ! gives tiny
>         j=z'44434241'                           ! gives "ABCD"
>
> Everything works perfectly.

None of these are standard Fortran. The fact that some particular
compiler might happen to accept them is another matter; they are not
Fortran. In fact, because these violate a constraint (C410 in F2003 or
an even more stringent one in f95), the compiler is required to be able
to diagnose their usage. Have you tried the compiler switch to warn
about nonstandard forms? If you did so and the compiler failed to give
you a message about these, then the compiler violates the standard.

> I can assign directly a binary
> representation to an integer and to a real,

The ones assigning directly to a real are particularly nonportable. Even
among compilers that accept the nonstandard syntax, you will find
differences in interpretation of this. Indeed, the most "natural"
extension of the standard would not give the result you expect.

> and I can even assign it to
> a string if this is in equivalence with an appropriate integer.

Such an equivalence is also nonstandard.

It appears that you are not actually comparing the Fortran language to
other languges, but instead comparing a particular Fortran compiler.
That's not the same thing.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/15/2009 4:27:54 PM

```LC's No-Spam Newsreading account wrote:
....
>      short i ;
>      i=somevalue;
>      printf("%6.5d %6.6o %4.4X %d \n",i,i,i,sizeof(i)) ;

The '%o" and "%X" format specifiers require an unsigned int argument,
'i' doesn't qualify. The "%d" format specifier require an int. This is
OK for the first "%d", because 'i' is automatically promoted to an
'int'. It is not OK for the final %d, because sizeof expressions have
a value of type size_t, which is not only unsigned, but on many
platforms is larger than an int.

>      int j ;
>      j=somevalue ;
>      printf("%11.10d %11.11o %8.8X %d \n",j,j,j,sizeof(j)) ;

Exactly the same issues apply here.

>      float f ;
>      f=somevalue ;
>      printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;

The problems with the "%o" and "%X" format specifiers in this case are
technically exactly the same as in the previous two cases. However,
while there are many systems where they will work as you might expect
them to with a signed int value, there's very few, if any, systems
where they'll work with floating point values.

> Here I find two problems, a minor and a major one
>
>    The minor one is that a positive short is displayed OK
>    But a negative short is displayed with too many oct and hex digits
>      i=32767 ;        /*  32767      077777     7FFF */
>      i=-1;            /* -00001 37777777777 FFFFFFFF */
>
>    although a sizeof says that i is 2 bytes

'i' is promoted to an int before being passed to printf(), and you
printed it using a format specifier for an unsigned int. Why do you
think that sizeof(short) has anything to do with the result that you
get?

> The major problem is that an assignment to a float gives an
> unexpected result (no compile or runtime error)

No, the major problem is that you expected any particular result. The
standard does not provide any support for any such expectations. If
printf() had decided to print out "You have no idea what you're
doing.", it would have been both fully conforming and fairly accurate.

>      f=0X40800000;  /* should return 4.0  */

0x40800000 is a hex constant with a value of  1082130432. Assigning it
to a float object causes it to be converted to one of the two values
representable as a float that are closest to 1082130432.0, which will
usually be1082130432.0 itself, except in the unlikely (but legal) case
where FLT_RADIX is something other than a small power of 2 . Why would
expect the result to be 4.0?

>      f=0X80800000;  /* should return tiny */

I don't believe that a value of 2155872256.0 counts as tiny, though
astronomers might disagree.

> For instance the latter returns 2.155872e+09, the former 2.155872e+09
> and BOTH THE SAME 00000000000 as octal and 41E01000 as hex (different
> from the one I assigned)

Well, when you ask printf() to print an unsigned integer, and you give
it a floating point value instead, you really can have no justified
grounds for complaint, regardless of what it prints.
```
 0
Reply jameskuyper (5639) 6/15/2009 4:49:18 PM

```"LC's No-Spam Newsreading account" <nospam@mi.iasf.cnr.it> wrote in message
news:alpine.LSU.2.00.0905281151430.4739@cbfrvqba.ynzoengr.vans.vg...

>        j=z'7FFE'                               ! gives 32866
>        j=o'37777777776'                        ! give  -2
>        j=b'11111111111111111111111111111110'
>        r=z'80800000'                           ! gives tiny
>        j=z'44434241'                           ! gives "ABCD"

A problem here is that the above isn't legal Fortran, not even F08.  The
key ambiguity lies in the assignment:

r = z'80800000'

which is supposed to yield -tiny(0.0).  It is controversial what a
compiler should do here: should it interpret z'80800000' as a
Hollerith constant and assign as if via TRANSFER (with result -tiny(0.0))
or should it be treated as an integer constant, thus -2139095040?
F08 allows different conpilers to interpret this differently, even
when couched as a DATA statement by disallowing the assignment form
entirely and only permitting the DATA statement form when the
corresponding data-stmt-object is of type integer.  The result is that
compilers can accept their traditional form as an extension and users
of a given compiler don't have to change their hoary code because the
compiler wasn't required to changed its behavior by the standard.

F08 does have a form where the programmer is required to specify
which interpretation he wants:

r = INT(z'80800000') ! r = -2139095040
r = REAL(z'80800000') ! r = -tiny(0.0)

> I then moved to C, I tried statements like

>     short i ;
>     i=somevalue;
>     printf("%6.5d %6.6o %4.4X %d \n",i,i,i,sizeof(i)) ;

>     int j ;
>     j=somevalue ;
>     printf("%11.10d %11.11o %8.8X %d \n",j,j,j,sizeof(j)) ;

>     float f ;
>     f=somevalue ;
>     printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;

> Here I find two problems, a minor and a major one

>   The minor one is that a positive short is displayed OK
>   But a negative short is displayed with too many oct and hex digits
>     i=32767 ;        /*  32767      077777     7FFF */
>     i=-1;            /* -00001 37777777777 FFFFFFFF */

>   although a sizeof says that i is 2 bytes

In the above, i was printed with the %o format.  The mechanism for
passing i to printf means that there is no way for the printf
function to distinguish it from an int, so the calling program
has to convert to type int via sign extension (so that it could
print (short)(-1) as -1 with a %d format) and printf doesn't know
that it started life as a short so you get what you get.  If you
don't like it, you can always change the format to "%6.6ho".

> The major problem is that an assignment to a float gives an unexpected
> result (no compile or runtime error)

>     f=0X40800000;  /* should return 4.0  */
>     f=0X80800000;  /* should return tiny */

> For instance the latter returns 2.155872e+09, the former 2.155872e+09 and
> BOTH THE SAME 00000000000 as octal and 41E01000 as hex (different from the
> one I assigned)

C defines hex constants as being unsigned ints, maybe unsigned long ints,
I'm not clear on the fine points, but you should definitely get the big
numbers you are getting.  I haven't thought about the octal and hex
outputs you report above.  That's a different problem.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end

```
 0
Reply not_valid (1693) 6/15/2009 5:00:26 PM

```LC's No-Spam Newsreading account wrote:

> for instance the latter returns -2.139095e+09 and the one for 4.0
> returns 1.082130e+09

Huh.  Mine seems fine.  What hardware do you run on and what Java
compiler do you use?  SSCCE?

<code>
/** Java float test */
public class FloatTest {

public static void main(String[] args) {
float f = 1.0f;
int fi = Float.floatToRawIntBits(f);
f = Float.intBitsToFloat( 0x3f800000 );
System.out.printf("%x\n", fi );
System.out.printf("%g\n", f );
}
}

</code>

<output>

run:
3f800000
1.00000
BUILD SUCCESSFUL (total time: 0 seconds)

</output>
```
 0
Reply nospam977 (12) 6/15/2009 5:06:17 PM

```In comp.lang.fortran LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:
(snip)

< As a reference I started in Fortran with cases like these (I did also
< byte, short and 64bit integers, not shown) :

<        integer j
<        j=somevalue
<        write(*,3)j,j,j,j
< 3      format(I11.10,1X,B32.32,1X,O11.11,1X,Z8.8)

I believe this is right, though I am not so srue about the
part after the decimal point.

<        real r
<        r=somevalue
<        write(*,4)r,r,r,r
< 4      format(G13.7 ,1X,B32.32,1X,O11.11,1X,Z8.8)

This is non-standard, and likely won't work with some systems.
As default real and default integer are supposed to be the same
size, it should work with TRANSFER (and likely also with
EQUIVALENCE).

<        character*4 s
<        equivalence (j,s)
<        s=somestring
<        write(*,5)s,s,s,s
< 5      format(A4    ,1X,B32.32,1X,O11.11,1X,Z8.8)

Even less likely to work than REAL.  Again TRANSFER is
a good solution.  Though there is no guarantee that a default
integer is four characters long.

< I tried first with some explicit values (1, -1, 32767, 1.0, 2.0,
< huge(0.0), tiny(0.0), "ABCD") and obtained perfectly meaningful binary,
< oct and hex values. Then I replaced the assignment using bin, oct or hex
< constants

<        j=z'7FFE'                               ! gives 32866
<        j=o'37777777776'                        ! give  -2
<        j=b'11111111111111111111111111111110'
<        r=z'80800000'                           ! gives tiny
<        j=z'44434241'                           ! gives "ABCD"

< Everything works perfectly. I can assign directly a binary
< representation to an integer and to a real, and I can even assign it to
< a string if this is in equivalence with an appropriate integer.

That seems likely not to work on many systems.  Fortran 2003 suggest
that the REAL function should work in the REAL case.  I suppose
TRANSFER for the string case.

< I then moved to C, I tried statements like

<     short i ;
<     i=somevalue;
<     printf("%6.5d %6.6o %4.4X %d \n",i,i,i,sizeof(i)) ;

<     int j ;
<     j=somevalue ;
<     printf("%11.10d %11.11o %8.8X %d \n",j,j,j,sizeof(j)) ;

<     float f ;
<     f=somevalue ;
<     printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;

< Here I find two problems, a minor and a major one

<   The minor one is that a positive short is displayed OK
<   But a negative short is displayed with too many oct and hex digits
<     i=32767 ;        /*  32767      077777     7FFF */
<     i=-1;            /* -00001 37777777777 FFFFFFFF */

You can't printf short values.  They are converted to int before
they are passed to printf.  Bitwise AND (&) with the appropriate
constant, such as 0xffff first.

<   although a sizeof says that i is 2 bytes

< The major problem is that an assignment to a float gives an
< unexpected result (no compile or runtime error)

<     f=0X40800000;  /* should return 4.0  */
<     f=0X80800000;  /* should return tiny */

The hex constant is just an ordinary unsigned int and is converted
as usual.  The usual way to do this, though non standard, is with
the use of pointers.

< For instance the latter returns 2.155872e+09, the former 2.155872e+09
< and BOTH THE SAME 00000000000 as octal and 41E01000 as hex (different
< from the one I assigned)

< In Java I tried

<             int i ;
<             System.out.format("i is: %11d %11o %8x %n", i,i,i);

<             float f ;
<             System.out.format("f is: %e          %n", f    );

Look at the FloatToIntBits and IntToFloatBits functions.
(I might have the names slightly wrong.)  Also you might
like the DoubleToLongBits and LongToDoubleBits functions.
(oops, static methods.)

< Here format does not support the o and x descriptors for float argument.

< Anyhow I tested assignments for integer and they do work

<             i=037777777776 ;  /* -2    */
<             i=0X7FFE ;        /* 32766 */

< while assignment for real do not work (as in C)

<             f=0X3F800000;     /* should be 1.0 */
<             f=0X40800000;     /* should be 4.0 */
<             f=0X80800000;     /* should by tiny */

< (the compiler does not complain, there are no runtime exceptions, but
< the result is not what expected

Why is the result not expected?  You are assigning an integer
constant to a float variable.  Though as Java requires IEEE
floating point and supplies the conversion functions it should
work if done right.

< for instance the latter returns -2.139095e+09 and the one for 4.0
< returns 1.082130e+09

< I haven't tested assignment of hex or oct constants to strings in
< neither of the two latter languages (I guess Java will be using unicode,
< not plain ascii)

-- glen

```
 0
Reply gah (12850) 6/15/2009 5:12:30 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:

> I am collecting a sort of phrase books with equivalent "things" in
> various languages.
<snip>
> The major problem is that an assignment to a float gives an unexpected
> result (no compile or runtime error)
>
>     f=0X40800000;  /* should return 4.0  */
>     f=0X80800000;  /* should return tiny */

You've had this explained, so I will just add that C99 does allow you
to specify a floating point constant in hexadecimal.  They look like
this:

float x = 0x3.f8p-2f;

The exponent is decimal -- the trailing f simply marks this as a float
(rather than a double) and is not a digit in the exponent.  All of the
letters that are used in these constants can be in either case.

<snip>
--
Ben.
```
 0
Reply ben.usenet (6790) 6/15/2009 5:12:45 PM

```On Jun 15, 1:06=A0pm, markspace <nos...@nowhere.biz> wrote:
> LC's No-Spam Newsreading account wrote:
>
> > for instance the latter returns -2.139095e+09 and the one for 4.0
> > returns 1.082130e+09
>
> Huh. =A0Mine seems fine. =A0What hardware do you run on and what Java
> compiler do you use? =A0SSCCE?
>
> <code>
> /** Java float test */
> public class FloatTest {
>
> =A0 =A0 =A0public static void main(String[] args) {
> =A0 =A0 =A0 =A0 =A0float f =3D 1.0f;
> =A0 =A0 =A0 =A0 =A0int fi =3D Float.floatToRawIntBits(f);
> =A0 =A0 =A0 =A0 =A0f =3D Float.intBitsToFloat( 0x3f800000 );
> =A0 =A0 =A0 =A0 =A0System.out.printf("%x\n", fi );
> =A0 =A0 =A0 =A0 =A0System.out.printf("%g\n", f );
> =A0 =A0 =A0}
>
> }
>
> </code>
>
> <output>
>
> run:
> 3f800000
> 1.00000
> BUILD SUCCESSFUL (total time: 0 seconds)
>
> </output>

The OP didn't use Float.intBitsToFloat(), but directly assigned the
int value to the float.  Naturally that invoked the usual int-to-float
conversion, which was not what the OP wanted, but it is what the Java
language promises to do.

--
Lew
```
 0
Reply lew (2468) 6/15/2009 6:33:41 PM

```Lew wrote:
>
> The OP didn't use Float.intBitsToFloat(), but directly assigned the
> int value to the float.  Naturally that invoked the usual int-to-float
> conversion, which was not what the OP wanted, but it is what the Java
> language promises to do.

Ah, ok.  "Pilot error."
```
 0
Reply nospam977 (12) 6/15/2009 6:37:23 PM

```Lew <lew@lewscanon.com> wrote:

> On Jun 15, 1:06 pm, markspace <nos...@nowhere.biz> wrote:

> The OP didn't use Float.intBitsToFloat(), but directly assigned the
> int value to the float.  Naturally that invoked the usual int-to-float
> conversion, which was not what the OP wanted, but it is what the Java
> language promises to do.

It is also what some Fortran compilers are likely to do with the OP's
original nonstandard "Fortran" code. There appears to be an element of
commonality across the languages here. I'd say that the most significant
element of commonality is the unsupported nature of the OP's
expectations.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/15/2009 6:45:33 PM

```LC's No-Spam Newsreading account wrote:
> while assignment for real do not work (as in C)
>
>             f=0X3F800000;     /* should be 1.0 */
>             f=0X40800000;     /* should be 4.0 */
>             f=0X80800000;     /* should by tiny */
>
> (the compiler does not complain, there are no runtime exceptions, but
> the result is not what expected

Actually, according to the JLS, this is very much expected. The
hexadecimal literals are, of course, integers, and assigning an integer
to a float converts the integer into the closest representation in the
float value set.

> I haven't tested assignment of hex or oct constants to strings in
> neither of the two latter languages (I guess Java will be using unicode,
> not plain ascii)

In Java, the conversion of constants would be via StringBuffer's
toString(int) method, which would just print out the number in nominal
decimal format. Strings are internally stored in Java as UTF-16, but
conversion to bytes is often handled as UTF-8 or the platform default
encoding, which is almost always backwards-compatible with ASCII (I
think pretty much everything but multiple-bit fixed-width encodings and
EBCDIC).

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth
```
 0
Reply Pidgeot18 (1522) 6/15/2009 10:37:40 PM

```On Mon, 15 Jun 2009 17:48:42 +0200, LC's No-Spam Newsreading account
<nospam@mi.iasf.cnr.it> wrote, quoted or indirectly quoted someone who
said :

>while assignment for real do not work (as in C)
>
>             f=0X3F800000;     /* should be 1.0 */

Why SHOULD it work the same as C?

For heaven's sake read up on the syntax rather than trying to guess
it.

See http://mindprod.com/jgloss/literal.html
http://mindprod.com/jgloss/cast.html
http://mindprod.com/jgloss/floatingpoint.html especially
longBitsToDouble
--
http://mindprod.com

If everyone lived the way people do in Vancouver, we would need three more entire planets to support us.
~ Guy Dauncey
```
 0
Reply see_website (5878) 6/15/2009 10:47:25 PM

```Roedy Green wrote:
> On Mon, 15 Jun 2009 17:48:42 +0200, LC's No-Spam Newsreading account
> <nospam@mi.iasf.cnr.it> wrote, quoted or indirectly quoted someone who
> said :
>
> >while assignment for real do not work (as in C)
> >
> >             f=0X3F800000;     /* should be 1.0 */
>
> Why SHOULD it work the same as C?

Keep in mind that LC's expected results for C are just as incorrect as
they are for java. Does the above code not work essentially the same
as in C? I'm no Java expert, but I thought that this was an area where
java is consistent with C.
```
 0
Reply jameskuyper (5639) 6/15/2009 11:29:46 PM

```In comp.lang.fortran jameskuyper <jameskuyper@verizon.net> wrote:

<> >             f=0X3F800000;     /* should be 1.0 */
<>
<> Why SHOULD it work the same as C?
>
< Keep in mind that LC's expected results for C are just as incorrect as
< they are for java. Does the above code not work essentially the same
< as in C? I'm no Java expert, but I thought that this was an area where
< java is consistent with C.

As integer constants, yes, the results will be pretty much
the same in Java and C.  As Java doesn't have the unsigned types
that C has, there might be some sign related effect.

Java has the conversion functions that allow one to copy bit
patterns into floating point variables.  In C you can do it
using pointers to unsigned char, if you know the length.

Java requires IEEE floating point, in C you get whatever floating
point is used on your system, possibly with an unusual endianness.
(Especially VAX where integers are little endian, and floating
point is not big or little endian.)

-- glen
```
 0
Reply gah (12850) 6/16/2009 12:36:36 AM

```Roedy Green <see_website@mindprod.com.invalid> writes:
> On Mon, 15 Jun 2009 17:48:42 +0200, LC's No-Spam Newsreading account
> <nospam@mi.iasf.cnr.it> wrote, quoted or indirectly quoted someone who
> said :
>
>>while assignment for real do not work (as in C)
>>
>>             f=0X3F800000;     /* should be 1.0 */
>
> Why SHOULD it work the same as C?

Because the language was designed to share the same syntax
as C for such things?

> For heaven's sake read up on the syntax rather than trying to guess
> it.

And what have you done about the syntax of C? It appears that you've
ascribed meaning to, and thence trusted, three of the words in a post
by someone who was demonstrably entirely ignorant about the subject
matter he was addressing. A foolish move.

Phil
--
Marijuana is indeed a dangerous drug.
It causes governments to wage war against their own people.
-- Dave Seaman (sci.math, 19 Mar 2009)
```
 0
Reply thefatphil_demunged (1650) 6/16/2009 7:06:27 AM

```On Mon, 15 Jun 2009, LC's No-Spam Newsreading account wrote:

> I am now considering the indication of constants as hex, oct or binary
> constants. I have considered fortran, C, Java, IDL and (my)sql. I have a
> question on the first three.

[examples snipped]

Thanks to everybody for the replies, which I can summarize as follows (I
will reply separately on specific questions).

- some of the features I used are non-standard
- in some languages a format specification (or edit
descriptor,whatever you call it) implies
or requires a particular data type (and may cause an implicit
conversion). In particular in C "'%o' and "%X' format specifiers
require an unsigned int"
- in some languages (or all ? definitely C and Java) hex or oct
constants are integer. There may be means to store an hex constant
into a float like Float.intBitsToFloat in Java

- it is not obvious to find the relevant information in the
documentation :-(

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 10:35:48 AM

```On Mon, 15 Jun 2009, Richard Maine wrote:
> LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

>>         j=z'7FFE'                               ! gives 32866
>>         r=z'80800000'                           ! gives tiny
>>         j=z'44434241'                           ! gives "ABCD"

> None of these are standard Fortran.

I must say I never used hex/oct/bin constants (hex for short in the
remainder of this post) in the past because they weren't standard. If I
needed to force a particular binary representation I used bit
manipulation (let's say that since at least 10 years with the demises of
the Vaxes, one can reasonably assume, but for the endianness,
2-complement integers and IEEE floating points).

But reading Metcalf, Reid and Cohen (Fortran 95/2003 explained) I got
the impression they were standardized NOW.

What is exactly non standard in my usage ?

- usage of hex constants in assignments instead of DATA ?
- usage of hex constants for non-integers ?
- usage of hex edit descriptor for non-integers ?

> Have you tried the compiler switch to warn about nonstandard forms? If
> you did so and the compiler failed to give you a message about these,
> then the compiler violates the standard.

It does (so far testing with ifort).

> The ones assigning directly to a real are particularly nonportable.
> Even among compilers that accept the nonstandard syntax, you will find
> differences in interpretation of this.

OK. Point taken.
I'd better revert to my old usages and consider hex constants as
something to avoid.

> It appears that you are not actually comparing the Fortran language to
> other languges, but instead comparing a particular Fortran compiler.

Well, unless one has access to The Standard Itself, the only way one can
gain experience is testing with specific compilers, and with the ones
one has at hand. In the past (with f77) I developed an idea of "the
common and reasonable extensions to the standard" working with HP, IBM,
VAX, Sun, DEC Alpha ... but that because I got exposed to such hardware
and OS.  Nowadays our environment is essentially a Linux/Intel one.

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 10:53:53 AM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:

> On Mon, 15 Jun 2009, LC's No-Spam Newsreading account wrote:
>
>> I am now considering the indication of constants as hex, oct or
>> binary constants. I have considered fortran, C, Java, IDL and
>> (my)sql. I have a question on the first three.
>
>   [examples snipped]
>
> Thanks to everybody for the replies, which I can summarize as follows
> (I will reply separately on specific questions).
>
>  - some of the features I used are non-standard
>  - in some languages a format specification (or edit
>    descriptor,whatever you call it) implies
>    or requires a particular data type (and may cause an implicit
>    conversion). In particular in C "'%o' and "%X' format specifiers
>    require an unsigned int"
>  - in some languages (or all ? definitely C and Java) hex or oct
>    constants are integer. There may be means to store an hex constant
>    into a float like Float.intBitsToFloat in Java

- C has hex floating point constants.
>
>  - it is not obvious to find the relevant information in the
>    documentation :-(

What is "the documenation"?  What I mean is you may simply be looking
in the wrong place.

--
Ben.
```
 0
Reply ben.usenet (6790) 6/16/2009 10:59:17 AM

```On Mon, 15 Jun 2009, jameskuyper wrote:
> LC's No-Spam Newsreading account wrote:

> The '%o" and "%X" format specifiers require an unsigned int argument,

I thought they were "universal" like O and Z in Fortran.

>>      i=32767 ;        /*  32767      077777     7FFF */
>>      i=-1;            /* -00001 37777777777 FFFFFFFF */
>>    although a sizeof says that i is 2 bytes
>
> 'i' is promoted to an int before being passed to printf(), and you

I wasn't aware of this. See above.

> printed it using a format specifier for an unsigned int. Why do you
> think that sizeof(short) has anything to do with the result that you
> get?

Expecting an universal edit descriptor, I expected that a 2-byte
quantity resulted in 4 hex digits.

>>      f=0X40800000;  /* should return 4.0  */

> Why would expect the result to be 4.0?

because that's the internal representation of the float 4.0 in IEEE
(just re-checked with my old Excel spreadsheet which gives the internal
representation of IEEE and VAX floats). I assumed that an "hex constant"
was just a bit pattern, with no type implied.

I realize now that, at least in C, hex constants are integer constants
(is this implicit or documented ?)

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 11:03:13 AM

```LC's No-Spam Newsreading account wrote:
> On Mon, 15 Jun 2009, LC's No-Spam Newsreading account wrote:
>
>> I am now considering the indication of constants as hex, oct or binary
>> constants. I have considered fortran, C, Java, IDL and (my)sql. I have
>> a question on the first three.
>
>   [examples snipped]
>
> Thanks to everybody for the replies, which I can summarize as follows (I
> will reply separately on specific questions).
>
>  - some of the features I used are non-standard
>  - in some languages a format specification (or edit
>    descriptor,whatever you call it) implies
>    or requires a particular data type  ...

Correct so far.

>    ... (and may cause an implicit
>    conversion).  ...

Incorrect, at least with regard to printf() in C. The implicit
conversions we told you about are the default argument promotions that
occur as the result of passing an unprototyped argument to a function,
they have no direct connection to the format specifiers. While there is
a prototype in <stdio.h> for printf(), only the first two arguments have
explicit types - the remaining objects are subject to only the default
argument promotions. Note, in particular, that the implicit conversion
may result is a type different from that specified by the corresponding
format specifier: that's what causes the problems.

>    ... In particular in C "'%o' and "%X' format specifiers
>    require an unsigned int"
>  - in some languages (or all ? definitely C and Java) hex or oct
>    constants are integer. There may be means to store an hex constant
>    into a float like Float.intBitsToFloat in Java
>
>  - it is not obvious to find the relevant information in the
>    documentation :-(

I can't address the quality of the documentation for whichever
implementation of the C standard library that you're using. However, the
C standard itself says this pretty clearly: "If any argument is not the
correct type for the corresponding conversion specification, the
behavior is undefined." (7.19.6.1p9), and the documentation for each
conversion specification identifies what the "correct type" is.

Any decent elementary C text should tell you that initializing an object
with a expression causes the expression's value to be converted to the
object's type and stored in the object. I can't really figure out why
you expected different behavior, but I doubt that it's the fault of your
text.
```
 0
Reply jameskuyper (5639) 6/16/2009 11:23:08 AM

```In article <alpine.LSU.2.00.0906161255000.6153@cbfrvqba.ynzoengr.vans.vg>, LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

>Expecting an universal edit descriptor, I expected that a 2-byte
>quantity resulted in 4 hex digits.

Not if you tell it explicitly you want 8...
```
 0
Reply spambait4 (1173) 6/16/2009 11:41:48 AM

```On Mon, 15 Jun 2009, glen herrmannsfeldt wrote:
> LC's No-Spam Newsreading account wrote:

> Even less likely to work than REAL.  Again TRANSFER is a good
> solution.  Though there is no guarantee that a default integer is four
> characters long.

It is in practice in my case, and in all the environments I can
realistically work. No longer the time of 36-bit machines ...

> < In Java I tried

> Look at the FloatToIntBits and IntToFloatBits functions.

f = Float.intBitsToFloat( 0x3f800000 );
as another poster suggested. Thanks to both !

> Why is the result not expected?  You are assigning an integer
> constant to a float variable.

Well, my reference for Java is the tutorial on the java.sun.com site and
I've never found a CLEAR statement that an hex pattern is necessarily
typed as an integer. I assumed it to be an arbitrary bit pattern, which
could be reversed into any type of variable.

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 11:56:41 AM

```On Mon, 15 Jun 2009, Ben Bacarisse wrote:
> LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:
>

>>     f=0X40800000;  /* should return 4.0  */
>>     f=0X80800000;  /* should return tiny */

>  float x = 0x3.f8p-2f;

I tried to play with this form, e.g.

f=0X1.ap0f;        /* 1.625 */
f=0X1.ap1f;        /* 3.25  */
f=0X1.ap-1f;       /* 0.8125 */

But it is not obvious to me what the two parts are ... mantissa in hex
and exponent as power of 2 in decimal ... but are they the same that
constitute exactly the IEEE representation or can be scaled arbitrarily ?

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 12:03:12 PM

```On Mon, 15 Jun 2009, Roedy Green wrote:

> For heaven's sake read up on the syntax rather than trying to guess
> it.

java.sun.com tutorial and the API documentation (well, to find something
in the API documentation you have to know what to look already).

As said in other posts, my (wrong) assumption was that an hex "string"
like 0X40800000 would be just an arbitrary bit pattern which can be
transferred into any variable type, not an integer constant. I've never
encountered explicitly such definition. NOW I know.

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 12:06:39 PM

```On Mon, 15 Jun 2009, jameskuyper wrote:

>>      float f ;
>>      f=somevalue ;
>>      printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;
>
> The problems with the "%o" and "%X" format specifiers in this case are
> technically exactly the same as in the previous two cases. However,

Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to a
binary file and using od :-) ?

I tried the above using one of the following instead of "somevalue"
(with gcc)

f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
f=2.0f ;  /* gives 40000000                     */
f=4.0f ;  /* gives 40800000 instead of 40100000 */
f=8.0f ;  /* gives 41000000 instead of 40200000 */
C                   FORTRAN

For 2.0 I obtain the same binary representation I obtain in Fortran, for
the other values (note all powers of 2) I obtain discrepant values. 'm
pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
display of a real in IEEE and VAX form) the Fortran value is the correct
one (IEEE).

Is this a side effect of some signed vs unsigned thing ?

--
----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
```
 0
Reply nospam110 (157) 6/16/2009 12:20:17 PM

```LC's No-Spam Newsreading account wrote:
>
> Hmm... what's then the "standard" way to obtain an hex dump of a float
> (in the way the Z format will do in Fortran), other than writing it to a
> binary file and using od :-) ?

I'd do something like this (warning, been too long since C for me):

union float_int {
float f;
int i;
} x;

x.f = 1.0f;
printf( "%08.8X", x.i );
```
 0
Reply nospam977 (12) 6/16/2009 1:06:54 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:

> On Mon, 15 Jun 2009, Ben Bacarisse wrote:
>> LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:
>>
>
>>>     f=0X40800000;  /* should return 4.0  */
>>>     f=0X80800000;  /* should return tiny */
>
>>  float x = 0x3.f8p-2f;
>
> I tried to play with this form, e.g.
>
>     f=0X1.ap0f;        /* 1.625 */
>     f=0X1.ap1f;        /* 3.25  */
>     f=0X1.ap-1f;       /* 0.8125 */
>
> But it is not obvious to me what the two parts are ... mantissa in hex
> and exponent as power of 2 in decimal ... but are they the same that
> constitute exactly the IEEE representation or can be scaled
> arbitrarily ?

The bit before the p just gives the value as a hexadecimal fraction;
the bit after the p gives the exponent.  This is much more useful than
tying the notation to one specific representation of floating point
numbers.  Here are your example numbers in binary rather than hex:

1.101  = 1+1/2+1/8    = 1.625
11.01   = 2+1+1/4      = 3.25
0.1101 = 1/2+1/4+1/16 = 0.8125

--
Ben.
```
 0
Reply ben.usenet (6790) 6/16/2009 1:12:42 PM

```LC's No-Spam Newsreading account wrote:

> Well, my reference for Java is the tutorial on the java.sun.com site and
> I've never found a CLEAR statement that an hex pattern is necessarily
> typed as an integer. I assumed it to be an arbitrary bit pattern, which
> could be reversed into any type of variable.

You need a few more references.  The tutorial is just that, a tutorial.
It doesn't cover everything.  However it's not hard to type "Java
which do talk about hex literal constants.

The ultimate source is the JLS:

<http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.1>

Scroll down about one page to where it says "HexNumeral" which is where
you can see that the "0x" format is for integers.

Floating point hex numbers are available too.  Scroll down a bit more to
the section on floating point literals.  (The important difference
between hex integers and hex floats is that hex floats have a decimal
point: 0xAA.55)

But those hex floats are still *NUMBERS*, not *BIT PATTERNS*.  Use the
Float methods intToFloatBits and floatToIntBits to access floats as bit
patterns.

```
 0
Reply nospam977 (12) 6/16/2009 1:21:00 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:

> On Mon, 15 Jun 2009, jameskuyper wrote:
>
>>>      float f ;
>>>      f=somevalue ;
>>>      printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;
>>
>> The problems with the "%o" and "%X" format specifiers in this case are
>> technically exactly the same as in the previous two cases. However,
>
> Hmm... what's then the "standard" way to obtain an hex dump of a float
> (in the way the Z format will do in Fortran), other than writing it to
> a binary file and using od :-) ?

for (int b = 0; i < sizeof(float); i++)
printf("%02x", ((unsigned char *)&f)[i]);

but there is no shorthand for this because it is not needed much.  Any
actual dump of the representation will have to interpreted depending
on the internal format being used.

People want hex output in order to find out exactly what value is in a
float without worrying about the effect of conversion to decimal.  C
can do this more useful operation directly using the format %a (or %A).

Of course, if the machine uses decimal floating point, %f, %e and %g
give you the exact values and %a will make matters worse.

> I tried the above using one of the following instead of "somevalue"
> (with gcc)
>
>     f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
>     f=2.0f ;  /* gives 40000000                     */
>     f=4.0f ;  /* gives 40800000 instead of 40100000 */
>     f=8.0f ;  /* gives 41000000 instead of 40200000 */
>                        C                   FORTRAN
>
> For 2.0 I obtain the same binary representation I obtain in Fortran,
> for the other values (note all powers of 2) I obtain discrepant
> values. 'm pretty sure (checked with my old Excel spreadsheet doing
> the bit-by-bit
> display of a real in IEEE and VAX form) the Fortran value is the
> correct one (IEEE).
>
> Is this a side effect of some signed vs unsigned thing ?

Output from a program that "breaks the rules" is unreliable.  Your
code has undefined behaviour.  One might speculate on what comes out,
but you'd be better off avoiding undefined behaviour.

--
Ben.
```
 0
Reply ben.usenet (6790) 6/16/2009 1:26:47 PM

```LC's No-Spam Newsreading account wrote:

>  - There may be means to store an hex constant
>    into a float like Float.intBitsToFloat in Java
>

For Java, these MUST be present.  It's required, at least for Java SE
(as opposed to Java ME, which I think is still back on the 1.0 API).

>  - it is not obvious to find the relevant information in the
>    documentation :-(
>

results page.  This usually works for me, and did for "java tutorial hex."

The union keyword for C is a bit trickier to find.  However, making a
union of float and int is usually the first elementary example presented
seen it.  So the answer here is to read ALL the documentation, not just
some of it.  And for C I think a book like Kerrigan and Ritchie is a
rather short read, not hard at all.
```
 0
Reply nospam977 (12) 6/16/2009 1:30:18 PM

```On 16 June, 13:20, LC's No-Spam Newsreading account
<nos...@mi.iasf.cnr.it> wrote:
> On Mon, 15 Jun 2009, jameskuyper wrote:
> >> =A0 =A0 =A0float f ;
> >> =A0 =A0 =A0f=3Dsomevalue ;
> >> =A0 =A0 =A0printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;
>
> > The problems with the "%o" and "%X" format specifiers in this case are
> > technically exactly the same as in the previous two cases. However,
>
> Hmm... what's then the "standard" way to obtain an hex dump of a float
> (in the way the Z format will do in Fortran), other than writing it to a
> binary file and using od :-) ?
>
> I tried the above using one of the following instead of "somevalue"
> (with gcc)
>
> =A0 =A0 =A0f=3D1.0f ; =A0/* gives 3FF00000 instead of 3F800000 */
> =A0 =A0 =A0f=3D2.0f ; =A0/* gives 40000000 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 */
> =A0 =A0 =A0f=3D4.0f ; =A0/* gives 40800000 instead of 40100000 */
> =A0 =A0 =A0f=3D8.0f ; =A0/* gives 41000000 instead of 40200000 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 C =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 FORTRAN
>
> For 2.0 I obtain the same binary representation I obtain in Fortran, for
> the other values (note all powers of 2) I obtain discrepant values. 'm
> pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
> display of a real in IEEE and VAX form) the Fortran value is the correct
> one (IEEE).
>
> Is this a side effect of some signed vs unsigned thing ?

I tried this

#include <stdio.h>

void dump_val (unsigned char *p, size_t n)
{
size_t i;
for (i =3D 0; i < n; i++)
printf ("%.02x ", p[i] & 0xff);
printf ("\n");
}

void dump_double (double x)
{
unsigned char *p;
p =3D (unsigned char*)&x;
printf ("representation of %f is ", x);
dump_val (p, sizeof(x));}

int main (void)
{

dump_double (1.0);
dump_double (2.0);
dump_double (4.0);
dump_double (8.0);

return 0;
}

and got

representation of 1.000000 is 00 00 00 00 00 00 f0 3f
representation of 2.000000 is 00 00 00 00 00 00 00 40
representation of 4.000000 is 00 00 00 00 00 00 10 40
representation of 8.000000 is 00 00 00 00 00 00 20 40

[note: an earlier version of this program posted here
just repeatedly printed the first byte]

--
Nick Keighley

```
 0
Reply nick_keighley_nospam (4575) 6/16/2009 1:32:40 PM

```On 16 June, 14:06, markspace <nos...@nowhere.biz> wrote:
> LC's No-Spam Newsreading account wrote:
>
>
>
> > Hmm... what's then the "standard" way to obtain an hex dump of a float
> > (in the way the Z format will do in Fortran), other than writing it to =
a
> > binary file and using od :-) ?
>
> I'd do something like this (warning, been too long since C for me):
>
> =A0 =A0union float_int {
> =A0 =A0 =A0float f;
> =A0 =A0 =A0int i;
> =A0 =A0} x;
>
> =A0 =A0x.f =3D 1.0f;
> =A0 =A0printf( "%08.8X", x.i );

and if a float won't fit in an int?

```
 0
Reply nick_keighley_nospam (4575) 6/16/2009 1:33:15 PM

```LC's No-Spam Newsreading account wrote:
> On Mon, 15 Jun 2009, jameskuyper wrote:
>> LC's No-Spam Newsreading account wrote:
>
>> The '%o" and "%X" format specifiers require an unsigned int argument,
>
> I thought they were "universal" like O and Z in Fortran.

Did the documentation for those specifiers give you any justification
for such thinking? It should say something like the following: "The
unsigned int argument is converted to unsigned octal (o), unsigned
decimal (u), or unsigned hexadecimal notation (x or X)... "
(7.19.6.1p8). Note, in particular, that if the argument is not an
unsigned int, this description is meaningless, which is a strong hint
that the argument has to be an unsigned int.

....
>> 'i' is promoted to an int before being passed to printf(), and you
>
> I wasn't aware of this. See above.
>
>> printed it using a format specifier for an unsigned int. Why do you
>> think that sizeof(short) has anything to do with the result that you
>> get?
>
> Expecting an universal edit descriptor, I expected that a 2-byte
> quantity resulted in 4 hex digits.

I recommend learning a lot more about C, and in particular being more
careful to read the available documentation or textbooks, before forming
any more expectations about what C code will do. You're misinterpreting
some very elementary issues.

>>>      f=0X40800000;  /* should return 4.0  */
>
>> Why would expect the result to be 4.0?
>
> because that's the internal representation of the float 4.0 in IEEE
> (just re-checked with my old Excel spreadsheet which gives the internal
> representation of IEEE and VAX floats). ...

But did anyone tell you anything to suggest that the assignment operator
had any effect other than setting the left operand to represent as
closely as possible the save value as the right operand? In particular,
did anyone ever suggest to you that the assignment operator would set
the representation of the left operand, rather than the value it
represents, to match the right operand?

> ... I assumed that an "hex constant"
> was just a bit pattern, with no type implied.

No, a hex constant is just one of many different ways of writing an
integer constant. In C, an integer constant of 127 can be written as
127, 0x3F, 0177, '\x3f', or '\0177'. Any of the first three can be
followed by 'u', indicating unsigned, or by 'l', indicating a long int.
All of the letters given above (x, u, l, and the hex digits a, b, c, d,
e, and f) can be either upper or lower case.

> I realize now that, at least in C, hex constants are integer constants
> (is this implicit or documented ?)

It's documented very clearly in section 6.4.4 of the standard.
```
 0
Reply jameskuyper (5639) 6/16/2009 1:34:49 PM

```LC's No-Spam Newsreading account wrote:
> On Mon, 15 Jun 2009, jameskuyper wrote:
>
>>>      float f ;
>>>      f=somevalue ;
>>>      printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;
>>
>> The problems with the "%o" and "%X" format specifiers in this case are
>> technically exactly the same as in the previous two cases. However,
>
> Hmm... what's then the "standard" way to obtain an hex dump of a float
> (in the way the Z format will do in Fortran), other than writing it to a
> binary file and using od :-) ?

unsigned char *p = (unsigned char*)&f;
unsigned char *lim = p + sizeof f;

printf("%13.7g 0X", f);
while(p < limit)
printf("%02X", *p++);
printf("%zu\n", sizeof f);

Note: if you're using C90, replace that last line with:

printf("%lu\n", (unsigned long)sizeof f);

Note that this will not work as intended if UCHAR_MAX > 255. Writing the
code so that it will work properly for arbitrary values of UCHAR_MAX is
quite feasible, but it would add significantly to the complexity of the
code, which I think would only add to your confusion; since such systems
are rare, I kept the code simple by not dealing with them.

> I tried the above using one of the following instead of "somevalue"
> (with gcc)
>
>     f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
>     f=2.0f ;  /* gives 40000000                     */
>     f=4.0f ;  /* gives 40800000 instead of 40100000 */
>     f=8.0f ;  /* gives 41000000 instead of 40200000 */
>                        C                   FORTRAN
>
> For 2.0 I obtain the same binary representation I obtain in Fortran, for
> the other values (note all powers of 2) I obtain discrepant values. 'm
> pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
> display of a real in IEEE and VAX form) the Fortran value is the correct
> one (IEEE).
>
> Is this a side effect of some signed vs unsigned thing ?

Since the printf() call that you wrote has undefined behavior, there's
really nothing that can meaningfully be said about why you got the
results that you got.
```
 0
Reply jameskuyper (5639) 6/16/2009 1:51:27 PM

```Nick Keighley wrote:

>
> and if a float won't fit in an int?

Goes 'splody.  If you're up against platform dependencies (which you
will be in the real world), you might have to resort to #if

#if sizeof(int) == 4
#define INT4 int
#endif

#if sizeof(long) == 8
#define INT8 long
#endif

And lots more like that.  These sorts of things are needed for dealing
with IO and external file formats, ime.

Then go:

union float_int {
FLOAT4 f;
INT4 i;
} x;

Which will meet the op's request for 4 byte values.
```
 0
Reply nospam977 (12) 6/16/2009 1:55:05 PM

```markspace wrote:
> LC's No-Spam Newsreading account wrote:
>>
>> Hmm... what's then the "standard" way to obtain an hex dump of a float
>> (in the way the Z format will do in Fortran), other than writing it to
>> a binary file and using od :-) ?
>
> I'd do something like this (warning, been too long since C for me):
>
>   union float_int {
>     float f;
>     int i;
>   } x;
>
>   x.f = 1.0f;
>   printf( "%08.8X", x.i );

That code is problematic for several different reasons: it reads the
value of a different member of a union than the one last written,  it
reads the value of an 'int' object that might contain a trap
representation, and it passes an int value to a printf() call when
corresponding specifier is "%X". If sizeof(int) > sizeof(float), all of
those problems just got worse.

Even if none of the above issues apply, if sizeof(int) < sizeof(float),
or if 'int' has any padding bits, this code will not print the entire
representation, and the result you get will depend upon the byte order
of 'int'. I say "byte order" rather than endianess because it's possible
that sizeof int > 2, in which case there's many more possibilities than
just those two. I once saw a list identifying 12 of the 24 possible byte
ordering for 4-byte integers as being in current use, though there's
only 4 that are at all common.
```
 0
Reply jameskuyper (5639) 6/16/2009 2:04:06 PM

```"LC's No-Spam Newsreading account" <nospam@mi.iasf.cnr.it> wrote in message
news:alpine.LSU.2.00.0905281151430.4739@cbfrvqba.ynzoengr.vans.vg...
> I am collecting a sort of phrase books with equivalent "things" in
> various languages.
>
> I am now considering the indication of constants as hex, oct or binary
> constants.

PL/I constants:

bit constant                        '1011100'b
bit data hex constant:        '3ABC'B4
character hex constant      '2E59'X
binary constant                  10111001b
binary hex constant            '48AB'XN

```
 0
Reply robin_v (2738) 6/16/2009 2:04:29 PM

```In article <alpine.LSU.2.00.0906161411320.6153@cbfrvqba.ynzoengr.vans.vg> LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> writes:
....
>      f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
>      f=2.0f ;  /* gives 40000000                     */
>      f=4.0f ;  /* gives 40800000 instead of 40100000 */
>      f=8.0f ;  /* gives 41000000 instead of 40200000 */
>                         C                   FORTRAN
>
> For 2.0 I obtain the same binary representation I obtain in Fortran, for
> the other values (note all powers of 2) I obtain discrepant values.

The first column contains the hex representations of single precision
floating-point, the second the hex representations of double precision
floating-point with the last eight hex digits chopped off (they are all 0).

I think that you obtained the first column from Fortran and the seconde
from C, contrary to what you state.  And the second is expected from C,
as in printf the float argument is automatically converted to double.
--
dik t. winter, cwi, science park 123, 1098 xg amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn  amsterdam, nederland; http://www.cwi.nl/~dik/
```
 0
Reply Dik.Winter (1625) 6/16/2009 2:24:51 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

> On Mon, 15 Jun 2009, Richard Maine wrote:
> > LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:
>
> >>         j=z'7FFE'                               ! gives 32866
> >>         r=z'80800000'                           ! gives tiny
> >>         j=z'44434241'                           ! gives "ABCD"
>
> > None of these are standard Fortran.

> But reading Metcalf, Reid and Cohen (Fortran 95/2003 explained) I got
> the impression they were standardized NOW.

They are, but...

> What is exactly non standard in my usage ?
>
>   - usage of hex constants in assignments instead of DATA ?
>   - usage of hex constants for non-integers ?
>   - usage of hex edit descriptor for non-integers ?

Yes. All 3 of those. F2003 allows a few other places, but they are still
pretty limitted. Other posts have mentioned the reasons. In particular,
f2003 allows them as arguments to the real and integer intrinsics. That
provides a standard way to use them in assignments and for reals.

> I'd better revert to my old usages and consider hex constants as
> something to avoid.

They are ok with the above limitations.

> > It appears that you are not actually comparing the Fortran language to
> > other languges, but instead comparing a particular Fortran compiler.
>
> Well, unless one has access to The Standard Itself, the only way one can
> gain experience is testing with specific compilers

That is a severe overstatement at best. While textbooks are not
definitive in cases of disagreement of interpretation, they are
excellent sources for most people - probably better than the standard
itself in that they are usually easier to read. You mention Metcalf,
Reid, and Cohen above. That's a fine source - certainly far better than
just testing with a compiler.

Testing with a specific compiler is simply a horrible way to evaluate
standard conformance. I cannot count the number of times that point has
been reiterated in this forum, usually when someone cites the fact that
their code compiled as evidence that it must be ok (and they are wrong).
There are many, many things that realistically cannot be diagnosed by a
compiler. Testing with a compiler is a useful "sanity check" to help see
if you might have overlooked something, but that is only a backup, not
the primary source.

At the very least, be sure to turn on the compiler's switches for
diagnosing standard conformance. The Intel compiler (and those in its
heritage) is particularly notable for accepting large numbers of
nonstandard features without warning by default. I consider this a
shortcoming of that mostly decent compiler. But the compiler does have a
switch for diagnosing the use of many of those nonstandard forms.
Without using that switch, I can't regard testing with the compiler as
much more than a joke in terms of verifying standard conformance. With
the switch, it is probably as good as most other compilers. I expected
that it would probably disgnose these particular errors. But as noted
above, a compiler can never be very good.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/16/2009 3:00:45 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

> On Mon, 15 Jun 2009, jameskuyper wrote:
> > LC's No-Spam Newsreading account wrote:
>
> > The '%o" and "%X" format specifiers require an unsigned int argument,
>
> I thought they were "universal" like O and Z in Fortran.

You mean like the O and Z edit descriptor in Fortran are *NOT*? They
allow only integers in standard Fortran.

> I realize now that, at least in C, hex constants are integer constants
> (is this implicit or documented ?)

Again, just like in Fortran. Yes, this is documented.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/16/2009 3:04:39 PM

```LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:

>   - it is not obvious to find the relevant information in the
>     documentation :-(

I can't speak to whatever you are using as documentation for C, but you
mentioned MR&C as a source for Fortran. Dragging out my copy, most of
these issues look pretty clear in it to me.

The boz (binary, octal, and hex) literals are described in the section
on integer literal constants. The text says they are integers, in case
the section name wasn't enough clue. It then also says "The use of these
forms of constants is limitted to their appearance as implicit integers
in the data statement..."  That seems pretty direct to me.

For the edit descriptors, B, O, and Z are all listed only in the section
on integer (pg 197) and described as for integers.

The one thing that I would agree makes some material a little hard to
find is the way that the book separates out the new f2003 material. I
quickly found the material on boz literals on page 15. That doesn't
cover the f2003 feature of allowing those forms in some intrinsics. For
that, you need to go to the chapter on "miscellaneous enhancements", in
particular 18.9, which is even high enough level to be in the table of
contents. That section also mentions a little aabout the reasons for the
limitations, while page 15 was pretty much "just the facts."

I'd suggest that the bigger thing that would make this material hard to
find would be failing to make it a habit to look. That seems to go along
Itself, the only way one can gain experience is testing with specific
compilers".

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/16/2009 3:42:04 PM

```"Richard Maine" <nospam@see.signature> wrote in message
news:1j1e9fd.1nt57p6i2rv5cN%nospam@see.signature...

> The boz (binary, octal, and hex) literals are described in the section
> on integer literal constants. The text says they are integers, in case
> the section name wasn't enough clue. It then also says "The use of these
> forms of constants is limitted to their appearance as implicit integers
> in the data statement..."  That seems pretty direct to me.

> For the edit descriptors, B, O, and Z are all listed only in the section
> on integer (pg 197) and described as for integers.

> The one thing that I would agree makes some material a little hard to
> find is the way that the book separates out the new f2003 material. I
> quickly found the material on boz literals on page 15. That doesn't
> cover the f2003 feature of allowing those forms in some intrinsics. For
> that, you need to go to the chapter on "miscellaneous enhancements", in
> particular 18.9, which is even high enough level to be in the table of
> contents. That section also mentions a little aabout the reasons for the
> limitations, while page 15 was pretty much "just the facts."

There seems to have been a sea change in F03 where boz-literal-constants
can be regarded as bit sequences as arguments to INT and REAL, as in
N1723.pdf, section 13.3.3.  This usage seems more consistent with the
O.P.'s expectations.

C:\gfortran\clf\bit_sequence>type bit_sequence.f90
program test
implicit none
real x

x = real(z'3f800000',kind(x))
write(*,'(f0.1,1x,z8.8)') x, transfer(x,1)
end program test

C:\gfortran\clf\bit_sequence>gfortran -std=f2003
bit_sequence.f90 -obit_sequence

C:\gfortran\clf\bit_sequence>bit_sequence
1.0 3F800000

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end

```
 0
Reply not_valid (1693) 6/16/2009 4:26:55 PM

```"James Kuyper" <jameskuyper@verizon.net> wrote in message

> LC's No-Spam Newsreading account wrote:

>> I thought they were "universal" like O and Z in Fortran.

> Did the documentation for those specifiers give you any justification for
> such thinking? It should say something like the following: "The unsigned
> int argument is converted to unsigned octal (o), unsigned
> decimal (u), or unsigned hexadecimal notation (x or X)... " (7.19.6.1p8).
> Note, in particular, that if the argument is not an unsigned int, this
> description is meaningless, which is a strong hint that the argument has
> to be an unsigned int.

It seems to me that the O.P. really wants what conversion to an
unsigned type would give him.  Just look at what he expects for the
Fortran output.  Given that, his biggest problem is not specifying
the length of the output correctly in the format string:

C:\gfortran\clf\bit_sequence>type fmt.c
#include <stdio.h>

int main()
{
short i;

i = -2;
printf("%hd %6.6ho %4.4hx\n", i, i, i);
printf("%d %6.6o %4.4x\n", i, i, i);

return 0;
}

C:\gfortran\clf\bit_sequence>gcc -std=c99 fmt.c -ofmt

C:\gfortran\clf\bit_sequence>fmt
-2 177776 fffe
-2 37777777776 fffffffe

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end

```
 0
Reply not_valid (1693) 6/16/2009 4:42:31 PM

```James Kuyper wrote:
<snip>
>     unsigned char *p = (unsigned char*)&f;
>     unsigned char *lim = p + sizeof f;

For what it's worth, I've seen code like this:

float f;
int *p = (int*)&f;

not work.  Apparently, it's a C aliasing thing;  you can't depend on
pointers of one type to point to objects of another type (gcc has an
option to change this behavior).  The union is a safer way to go.

Louis
```
 0
Reply lkrupp_nospam1 (64) 6/16/2009 5:48:20 PM

```On 2009-06-16, Louis Krupp <lkrupp_nospam@indra.com.invalid> wrote:
> James Kuyper wrote:
><snip>
>>     unsigned char *p = (unsigned char*)&f;
>>     unsigned char *lim = p + sizeof f;
>
> For what it's worth, I've seen code like this:
>
>    float f;
>    int *p = (int*)&f;
>
> not work.  Apparently, it's a C aliasing thing;  you can't depend on
> pointers of one type to point to objects of another type (gcc has an
> option to change this behavior).  The union is a safer way to go.

A union is not safer. Storing an int to a union and accessing a float,
or vice versa, is not defined behavior.

The portable purpose of a union is to provide compact storage for a polymorphic
data representation, whereby all accesses to the union are by means of that
member which was most recently used to store to it (or another member which has
a compatible type).
```
 0
Reply kkylheku (2499) 6/16/2009 5:55:19 PM

```Kaz Kylheku <kkylheku@gmail.com> writes:

> On 2009-06-16, Louis Krupp <lkrupp_nospam@indra.com.invalid> wrote:
>> James Kuyper wrote:
>><snip>
>>>     unsigned char *p = (unsigned char*)&f;
>>>     unsigned char *lim = p + sizeof f;
>>
>> For what it's worth, I've seen code like this:
>>
>>    float f;
>>    int *p = (int*)&f;
>>
>> not work.  Apparently, it's a C aliasing thing;  you can't depend on
>> pointers of one type to point to objects of another type (gcc has an
>> option to change this behavior).  The union is a safer way to go.
>
> A union is not safer. Storing an int to a union and accessing a float,
> or vice versa, is not defined behavior.
>
> The portable purpose of a union is to provide compact storage for a polymorphic
> data representation, whereby all accesses to the union are by means of that
> member which was most recently used to store to it (or another member which has
> a compatible type).

This rather draconian restriction has been relaxed.  As a result, it
is reasonable to use a union with an array of unsigned char:

union rep {
float f;
unsigned char rep[sizeof(float)];
};

if you don't like using explicit pointers.

--
Ben.
```
 0
Reply ben.usenet (6790) 6/16/2009 7:24:03 PM

```Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> As a result, it is reasonable to use a union with an array of
> unsigned char:
>
>   union rep {
>       float f;
>       unsigned char rep[sizeof(float)];
>   };
>
> if you don't like using explicit pointers.

I like to do this kind of thing with memcpy():

int reinterpret_float_as_int(float f)
{
int x;
assert(sizeof f == sizeof x);
memcpy(&x, &f, sizeof x);
return x;
}

--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
```
 0
Reply blp (3955) 6/16/2009 7:33:31 PM

```James Van Buskirk <not_valid@comcast.net> wrote:

> There seems to have been a sea change in F03 where boz-literal-constants
> can be regarded as bit sequences as arguments to INT and REAL,

That's the feature I alluded to earlier. I don't think I would call it a
"sea change" though. Boz-literal constants are still very restricted in
where they can appear. The new feature was a bit of a compromise in that
it does allow them outside of data statements (that limitation was
painfully restrictive), but it avoids the problems of just allowing them
in arbitrary places. The new places allowed are contexts where the
intended meaning is both unambiguous and reasonably "obvious".

There was a proposal to allow them much more liberally, but that didn't
get very far. It had the problem that there were pretty much
irresolvable conflicts between consistency and some existing extensions.
Putting them in the INT and REAL intrinsics avoided such conflicts.
There were not inconsistent existing extensions, and it allowed the
kinds of things people (such as the OP, but he is far from the only one)
want to be able to do. It does have the disadvantage of being a bit
verbose, but for that verbosity you get obviously unambiguous.

To me, a "sea change" would be allowing them anywhere and having the
interpretation determined by context.

Hmm. I suppose I'll set followups, though people can override if they
like. This particular bit seems to have minimal relevance to C or Java
other than perhaps the side note that it has some simillarities to what
appears to be allowed in them. The syntax is different, but it appears
that they also have a capability to explicitly specify that a bit
pattern is to be interpreted as a real.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/16/2009 7:40:18 PM

```Louis Krupp wrote:
> James Kuyper wrote:
> <snip>
> >     unsigned char *p = (unsigned char*)&f;
> >     unsigned char *lim = p + sizeof f;
>
> For what it's worth, I've seen code like this:
>
>    float f;
>    int *p = (int*)&f;
>
> not work.

Correct. However, that's not the case for unsigned char*; it's
perfectly safe to convert a pointer to any object into a pointer to
unsigned char*, and to use that pointer to access the first sizeof
(object) bytes after that pointer.

> ...  Apparently, it's a C aliasing thing;  you can't depend on
> pointers of one type to point to objects of another type ...

Correct. The anti-aliasing rules are intended to allow a C compiler to
generate code which, for example, assumes without bothering to check,
that writes through a pointer to float will not interact with reads
through a pointer to int.

> .. The union is a safer way to go.

The footnote to section 6.5.2.3p4 says "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." That last sentence is the killer.
```
 0
Reply jameskuyper (5639) 6/16/2009 8:04:14 PM

```In comp.lang.fortran Richard Maine <nospam@see.signature> wrote:
<>
<>   - usage of hex constants in assignments instead of DATA ?
<>   - usage of hex constants for non-integers ?
<>   - usage of hex edit descriptor for non-integers ?

< Yes. All 3 of those. F2003 allows a few other places, but they are still
< pretty limitted. Other posts have mentioned the reasons. In particular,
< f2003 allows them as arguments to the real and integer intrinsics. That
< provides a standard way to use them in assignments and for reals.

I thought that tO and Z still didn't work with non-integer
(REAL, COMPLEX, and CHARACTER) data.  I would expect TRANSFER to
work, transfering the bits to the appropriate integer.

-- glen
```
 0
Reply gah (12850) 6/16/2009 8:49:08 PM

```In comp.lang.fortran LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:
< On Mon, 15 Jun 2009, jameskuyper wrote:

<>>      float f ;
<>>      f=somevalue ;
<>>      printf("%13.7g %11.11o %8.8X %d \n",f,f,f,sizeof(f)) ;

<> The problems with the "%o" and "%X" format specifiers in this case are
<> technically exactly the same as in the previous two cases. However,

< Hmm... what's then the "standard" way to obtain an hex dump of a float
< (in the way the Z format will do in Fortran), other than writing it to a
< binary file and using od :-) ?

Copy to the appropriate sized integer using memcpy() after
casting pointers to (unsigned char*).

< I tried the above using one of the following instead of "somevalue"
< (with gcc)

<     f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
<     f=2.0f ;  /* gives 40000000                     */
<     f=4.0f ;  /* gives 40800000 instead of 40100000 */
<     f=8.0f ;  /* gives 41000000 instead of 40200000 */
<                        C                   FORTRAN

I don't see how you got most of those.  Note that you can't
pass (float) values to printf, as they get converted to double
along the way.  You should print them with %8.8Lx, with the
assumption that (double) and (long long) are the same size.

X'3FF0000000000000' (with the appropriate endianness) is
right for IEEE double.

do i=0,10
write(*,'(Z8.8)') TRANSFER(2.0**i,1)
enddo
end

will print out the single precision powers of 2.0 in Fortran.

#include <stdio.h>
#include <math.h>
int main() {
float f;
int i,j;
for(i=0;i<=10;i++) {
f=pow(2.0,i);
memcpy((unsigned char*)&j,(unsigned char*)&f,sizeof(j));
printf("%8.8x\n",j);
}
}

Will, I believe, in standard C with the assumption that
sizeof(int)==sizeof(float).

< For 2.0 I obtain the same binary representation I obtain in Fortran, for
< the other values (note all powers of 2) I obtain discrepant values. 'm
< pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
< display of a real in IEEE and VAX form) the Fortran value is the correct
< one (IEEE).

< Is this a side effect of some signed vs unsigned thing ?

No, it is (float) vs. (double).

-- glen
```
 0
Reply gah (12850) 6/16/2009 9:13:54 PM

```glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:

> In comp.lang.fortran Richard Maine <nospam@see.signature> wrote:
> <>
> <>   - usage of hex constants in assignments instead of DATA ?
> <>   - usage of hex constants for non-integers ?
> <>   - usage of hex edit descriptor for non-integers ?
>
> < Yes. All 3 of those. F2003 allows a few other places, but they are still
> < pretty limitted. Other posts have mentioned the reasons. In particular,
> < f2003 allows them as arguments to the real and integer intrinsics. That
> < provides a standard way to use them in assignments and for reals.
>
> I thought that tO and Z still didn't work with non-integer
> (REAL, COMPLEX, and CHARACTER) data.

They don't. I think you misunderstood my response, perhaps from having
snipped slightly too much.

The above was a list of things that were nonstandard about the OP's
code. I was not saying that they were things that changed in f2003.
Indeed, nothing of this in the OP's code is any more standard in f2003
than f95. F2003 does allow hex literals in a few other contexts, but not
in quite the way done by the OP.

> I would expect TRANSFER to
> work, transfering the bits to the appropriate integer.

Me too.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
```
 0
Reply nospam47 (9744) 6/16/2009 9:16:28 PM

```glen herrmannsfeldt <gah@ugcs.caltech.edu> writes:

> In comp.lang.fortran LC's No-Spam Newsreading account <nospam@mi.iasf.cnr.it> wrote:
<snip>
> < Hmm... what's then the "standard" way to obtain an hex dump of a float
> < (in the way the Z format will do in Fortran), other than writing it to a
> < binary file and using od :-) ?
>
> Copy to the appropriate sized integer using memcpy() after
> casting pointers to (unsigned char*).

There is no need to cast since (modern) memcpy takes void * arguments
and the conversion is implicit as in Ben Pfaff's code example
elsewhere.

<snip>
> #include <stdio.h>
> #include <math.h>
> int main() {
> float f;
> int i,j;
> for(i=0;i<=10;i++) {
>    f=pow(2.0,i);
>    memcpy((unsigned char*)&j,(unsigned char*)&f,sizeof(j));

You can omit the casts and the ()s round j.  Of course you don't have
to, I am just saying you can in order to get a cleaner example:

memcpy((&j, &f, sizeof j);

>    printf("%8.8x\n",j);
>    }
> }

<snip>
--
Ben.
```
 0
Reply ben.usenet (6790) 6/16/2009 9:52:58 PM

```On 16 June, 14:55, markspace <nos...@nowhere.biz> wrote:
> Nick Keighley wrote:

> > and if a float won't fit in an int?
>
> Goes 'splody.

que?

>=A0If you're up against platform dependencies (which you
> will be in the real world), you might have to resort to #if

the trouble is the "union hack" invokes Undefined Behaviour.

> #if sizeof(int) =3D=3D 4
> #define INT4 int
> #endif
>
> #if sizeof(long) =3D=3D 8
> #define INT8 long
> #endif

puke. I *hate* code like this

> And lots more like that. =A0These sorts of things are needed for dealing
> with IO and external file formats, ime.

no they aren't. Define your external interfaces in terms of streams
of bytes (or octets if you want to be really cool) and write code
to read and write them into structures.

> Then go:
>
> =A0 =A0union float_int {
> =A0 =A0 =A0FLOAT4 f;
> =A0 =A0 =A0INT4 i;
> =A0 =A0} x;
>
> Which will meet the op's request for 4 byte values.

it's possible float won't fit in *any* integer type

```
 0
Reply nick_keighley_nospam (4575) 6/17/2009 7:27:21 AM

```On 16 June, 18:48, Louis Krupp <lkrupp_nos...@indra.com.invalid>
wrote:
> James Kuyper wrote:

> > =A0 =A0 unsigned char *p =3D (unsigned char*)&f;
> > =A0 =A0 unsigned char *lim =3D p + sizeof f;
>
> For what it's worth, I've seen code like this:
>
> =A0 =A0float f;
> =A0 =A0int *p =3D (int*)&f;
>
> not work.

so don't do it.

>=A0Apparently, it's a C aliasing thing; =A0you can't depend on
> pointers of one type to point to objects of another type

With the exception of unsigned char. An array of unsigned char
can be overlaid on any other type. No traps or other undefined
behviour. It's the C way of getting at the representation of
an object. Which is probably what the OP wants. I already posted
code to do this.

> (gcc has an option to change this behavior).

gcc is borken

> =A0The union is a safer way to go.

noooo!

--
Nick Keighley

"That's right!" shouted Vroomfondel "we demand rigidly defined
areas of doubt and uncertainty!"

```
 0
Reply nick_keighley_nospam (4575) 6/17/2009 7:33:40 AM

```On Mon, 15 Jun 2009 11:00:26 -0600, "James Van Buskirk"
<not_valid@comcast.net> wrote:

> "LC's No-Spam Newsreading account" <nospam@mi.iasf.cnr.it> wrote in message
> news:alpine.LSU.2.00.0905281151430.4739@cbfrvqba.ynzoengr.vans.vg...

<snip: wrongly assuming, among other things, that C assignment takes
the bitpattern of a hex constant to a floating-point representation>

> >     f=0X40800000;  /* should return 4.0  */
> >     f=0X80800000;  /* should return tiny */
>
> > For instance the latter returns 2.155872e+09, the former 2.155872e+09 and
> > BOTH THE SAME 00000000000 as octal and 41E01000 as hex (different from the
> > one I assigned)
>
> C defines hex constants as being unsigned ints, maybe unsigned long ints,

Nit: C integer constants, unless suffixed L or LL, are the 'lowest'
type at least as high as int sufficient to contain the value.

Unless suffixed U, decimal constants mostly stay signed:
C89: signed int, signed long, unsigned long /* exception */
C99: signed int, signed long, signed long long

but hex or octal try BOTH signed and unsigned:
C89: signed int, unsigned int, signed long, unsigned long
C99: same then signed long long, unsigned long long

Thus a 'full width' hex constant, like 0xF00D0EC0 on a 32-bit system,
will come out unsigned int, but not all values will.

> I'm not clear on the fine points, but you should definitely get the big
> numbers you are getting.  I haven't thought about the octal and hex
> outputs you report above.  That's a different problem.

```
 0
Reply dave.thompson2 (781) 7/1/2009 5:30:02 AM

55 Replies
70 Views

Similar Articles

12/6/2013 6:28:17 PM
page loaded in 7802 ms. (0)