Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > A basic (?) problem with addresses (gcc)

Reply
Thread Tools

A basic (?) problem with addresses (gcc)

 
 
Piotrne
Guest
Posts: n/a
 
      12-15-2010
Hi,

I have a strange problem with casting addresses to different
types. I have a float variable. The sequence of 4 bytes
representing its value should be copied to an int
(of the same size like float: 4 bytes) and then back
to the float variable. Example:

#include <stdio.h>

int main(int argc, char **argv)
{
float x = 4.3;
int y;

y = *(int*)&x; /* copying of 4 bytes to int */
x = *(float*)&y; /* and back to float */

printf("x=%f\n",x); /* 4.3 expected here */
printf("y=%d\n",y);
return 0;
}

I have compiled this example in Linux, using gcc 4.1.1, with
different optimization options. Here are the results:

$ gcc cast2.c
$ ./a.out
x=4.300000
y=1082759578

$ gcc -O2 cast2.c
$ ./a.out
x=-167393728255558576456059409056680378368.000000
y=134513634

The first result is correct, but what happened to the second?
Probably addresses have been shifted for some reason. But such
constructions seem to be an elementary property of the C language,
and they don’t work...

Regards
Piotr
 
Reply With Quote
 
 
 
 
Adrian
Guest
Posts: n/a
 
      12-15-2010
On 12/15/2010 06:52 AM, Piotrne wrote:
> Hi,


> $ gcc cast2.c
> $ ./a.out
> x=4.300000
> y=1082759578
>
> $ gcc -O2 cast2.c
> $ ./a.out
> x=-167393728255558576456059409056680378368.000000
> y=134513634

Hi Piotr

I tried this with gcc.4.5 and both versions produce the same expected
result (and assembler).

Have you tried compiling with -S to check the assembler, maybe 4.1 is
optimizing something away it should not.

I also tried gcc.4.1.1 on x64 and got 0 for the optomized version.

If you try compiling with -S you will see the optimized version has very
different assembler.

gcc.4.1.1 has had a few bugs.

HTH

Adrian Cornish


 
Reply With Quote
 
 
 
 
Morris Keesan
Guest
Posts: n/a
 
      12-15-2010
On Wed, 15 Dec 2010 08:52:41 -0500, Piotrne <>
wrote:

> Hi,
>
> I have a strange problem with casting addresses to different
> types. I have a float variable. The sequence of 4 bytes
> representing its value should be copied to an int
> (of the same size like float: 4 bytes) and then back
> to the float variable. Example:
>
> #include <stdio.h>
>
> int main(int argc, char **argv)
> {
> float x = 4.3;
> int y;
>
> y = *(int*)&x; /* copying of 4 bytes to int */
> x = *(float*)&y; /* and back to float */
>
> printf("x=%f\n",x); /* 4.3 expected here */
> printf("y=%d\n",y);
> return 0;
> }
>
> I have compiled this example in Linux, using gcc 4.1.1, with
> different optimization options. Here are the results:
>
> $ gcc cast2.c
> $ ./a.out
> x=4.300000
> y=1082759578
>
> $ gcc -O2 cast2.c
> $ ./a.out
> x=-167393728255558576456059409056680378368.000000
> y=134513634
>
> The first result is correct, but what happened to the second?
> Probably addresses have been shifted for some reason. But such
> constructions seem to be an elementary property of the C language,
> and they don’t work...


Casting a pointer to a pointer of a different type is not guaranteed
to work. Worth trying here would be adding the lines

if (sizeof(int) != sizeof(float))
printf("int and float different sizes\n");

if ((void *)&x != (void *)(int *)&x)
printf("Casting &x to (int *) changes its value\n");

if ((void *)&y != (void *)(float *)&x)
printf("Casting &y to (float *) changes its value\n");


The optimizer may be changing the alignment requirements of float and
int objects. If you're trying to copy bytes between incompatible
types, using memcpy() would seem safer and more readable.
But what you're trying to do here seems suspicious, in any case.
--
Morris Keesan --
 
Reply With Quote
 
Piotrne
Guest
Posts: n/a
 
      12-15-2010
Morris Keesan pisze:

> Casting a pointer to a pointer of a different type is not guaranteed
> to work.


The value of the pointer should be retained and is:

Worth trying here would be adding the lines
>
> if (sizeof(int) != sizeof(float))
> printf("int and float different sizes\n");
>
> if ((void *)&x != (void *)(int *)&x)
> printf("Casting &x to (int *) changes its value\n");
>
> if ((void *)&y != (void *)(float *)&x)
> printf("Casting &y to (float *) changes its value\n");


I have checked them (changing x to y in the last "if")
and got no messages, in both compiled versions - in the
optimized, with wrong copying, too.

I have even checked (by printing) values of addresses after
casting to float* or int* - they are the same.

It seems, that the way how the pointer is used to read
memory causes problems. Placing the float variable
in an array (as a middle element of it) changes
the result. Anyway, it is strange. I'll write if I find
something about this.

Piotr



 
Reply With Quote
 
Piotrne
Guest
Posts: n/a
 
      12-15-2010
Morris Keesan wrote:

> Casting a pointer to a pointer of a different type is not guaranteed
> to work.


The value of the pointer should be retained and is:

> Worth trying here would be adding the lines
>
> if (sizeof(int) != sizeof(float))
> printf("int and float different sizes\n");
>
> if ((void *)&x != (void *)(int *)&x)
> printf("Casting &x to (int *) changes its value\n");
>
> if ((void *)&y != (void *)(float *)&x)
> printf("Casting &y to (float *) changes its value\n");


I have checked them (changing x to y in the last "if")
and got no messages, in both compiled versions - in the
optimized, with wrong copying, too.

I have even checked (by printing) values of addresses after
casting to float* or int* - they are the same.

It seems, that the way how the pointer is used to read
memory causes problems. Placing the float variable
in an array (as a middle element of it) changes
the result. Anyway, it is strange. I'll write if I find
something about this.

Piotr
 
Reply With Quote
 
Piotrne
Guest
Posts: n/a
 
      12-15-2010
pete wrote:

> (sizeof (float) == 4) isn't an elementary property
> of the C language.


In this case it is satisfied, I have removed the check
to make the code shorter.

P.


 
Reply With Quote
 
Nick Bowler
Guest
Posts: n/a
 
      12-15-2010
On Wed, 15 Dec 2010 20:18:58 +0100, Piotrne wrote:
> It seems, that the way how the pointer is used to read memory causes
> problems. Placing the float variable in an array (as a middle element
> of it) changes the result. Anyway, it is strange. I'll write if I find
> something about this.


Newer versions of GCC have an optimization called "strict aliasing",
enabled by default at the higher -O levels. It allows the compiler to
assume (among other things) that pointers to int are never used to
access objects of type float and vice versa. Such behaviour is
consistent with the C standard. Violating that assumption will lead
to unpredictable consequences.
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      12-15-2010
On 2010-12-15, Piotrne <> wrote:
> The first result is correct, but what happened to the second?


Your code was wrong. The compiler did whatever it wanted.

> Probably addresses have been shifted for some reason. But such
> constructions seem to be an elementary property of the C language,
> and they don???t work...


Nope. You invoked undefined behavior, the compiler caught you at it.

Don't do that.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      12-15-2010
Piotrne <> writes:
> I have a strange problem with casting addresses to different
> types. I have a float variable. The sequence of 4 bytes
> representing its value should be copied to an int
> (of the same size like float: 4 bytes) and then back
> to the float variable. Example:
>
> #include <stdio.h>
>
> int main(int argc, char **argv)
> {
> float x = 4.3;
> int y;
>
> y = *(int*)&x; /* copying of 4 bytes to int */
> x = *(float*)&y; /* and back to float */
>
> printf("x=%f\n",x); /* 4.3 expected here */
> printf("y=%d\n",y);
> return 0;
> }


Your code is at least non-portable. It assumes, among other things,
that int and float are the same size and that they have similar
alignment requirements. Your system (apparently) happens to satisfy
those assumptions, but others may not.

Even so, the compiler may assume that a float* won't be used to access
an int object, and that an int* won't be used to access a float object.

If you really want to copy the representation of one object into an
object of a different type, use memcpy().

What exactly are you trying to accomplish?

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      12-15-2010


"Seebs" <usenet-> wrote in message
news:slrnigi7cp.14pa.usenet-...
> On 2010-12-15, Piotrne <> wrote:
>> The first result is correct, but what happened to the second?

>
> Your code was wrong. The compiler did whatever it wanted.
>
>> Probably addresses have been shifted for some reason. But such
>> constructions seem to be an elementary property of the C language,
>> and they don???t work...

>
> Nope. You invoked undefined behavior, the compiler caught you at it.
>


What was wrong with it? Assuming int and float are the same sizes and are
aligned in a compatible way.

--
Bartc


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to implement a firewall for Windows platform that blocks based on Mac addresses instead of IP addresses cagdas.gerede@gmail.com C Programming 1 12-07-2006 04:30 AM
Physical Addresses VS. Logical Addresses namespace1 C++ 3 11-29-2006 03:07 PM
What is the difference between Visual Basic.NET and Visual Basic 6? Jimmy Dean Computer Support 3 07-25-2005 07:05 AM
Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET Jaime MCSD 2 09-20-2003 05:16 AM
Basic question about casting and addresses drowned C++ 4 08-03-2003 12:25 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57