This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Calling a function with a float argument modifies caller's state.



Thank you for your replies. My responses are below.



On 20/08/2012 22:21, Jeff B wrote:

(...)

WHY is a 32-bit float passed to a function in a manner different from a
32-bit int???
On 21/08/12 08:40, David Brown wrote:

A 32-bit float and a 32-bit int are completely different things.

I am completely aware of that.



The
fact that the have a common size is just coincidence.  The compiler
can treat them totally differently -

Obviously it is treating them very differently.



on many targets (including, I
believe, the x86 - depending on the compiler flags) they will be
passed around in different registers.  If it suits the cpu in
question, the compiler can happily convert the 32-bit float to a
64-bit (or even higher) resolution before passing it around.  You
certainly cannot rely on being able to convert randomly between ints
and floats while keeping the same exact values.

I am completely aware of the limitations of conversions. That is not the issue.


When passing data into printf(), the compiler can take the actual
format string into account.

I am aware of that too. I am not concerned that the output might be garbled.



When you write "printf("%f", x)", you are
/not/ saying "pass a 32-bit value x, treat it as representing a float,
and print it".

I considered that too, but that is not the issue. I can understand that the value might get printed out in some way I didn't expect.


The compiler may /choose/ to treat it that way.  But
it can also validly interpret it as "treat the value x as a float, and
print it out".  When you use C properly, according to the
specifications of printf, these do the same thing - but one way might
do it with smaller or faster code, or with better static error
checking.  When you break C rules by your mixed casting, they can mean
different things.

I also think that it is a really bad idea to have undocumented side
effects
like that.  Or did I already say that?

I think most people will agree that undocumented side effects are a
bad idea.  But your program does not demonstrate undocumented side
effects.

Well, a variable I am able to access from main() is changing even tho there is nothing in main() itself which is changing it. I do not change the variables after I init them:

    floatVarA = 1234.0;
    floatVarB = 5678.0;


(int)floatVarA = 0.000000 <<=== initial value 0?? floatVarA = 1234.000000 (int)floatVarA = 1234.000000 <<=== changed floatVarB = 5678.000000 (int)floatVarA = 5678.000000 <<=== changed again floatVarA = 1234.000000


The only thing I am doing is calling printf() and passing the variables by value. Neither am I using any printf() format which is going to send data back to main(), eg %n. So why is something visible to main() changing, however esoteric?

BTW I was originally putting values into a small array of
doubles (to force alignment) so that I could print them out
in hex, which is not an unreasonable thing to do.  Then I tried
to print the actual values with proper interpretation  from
said buffer using the proper printf() format and with proper
casts, which is also not an unreasonable thing to do.  Casting
as float with printf() format %f failed that exercise, outputting
"-nan".

When I started poking at it that's when I discovered that passing
a float variable (or float constant) was causing a value to change
in main().  The equivalent code with the same sized ints does not
exhibit that behavior.


Your program demonstrates that when you write code that has undefined
behaviour, it does not work as you expect.  That should not be a big
surprise.

I agree about using code with undefined behavior. Regardless of whatever confusion printf() may have about how to actually print something, it seems to me that (int)floatVar ought to be getting the bits from the same place as (float)floatVar. Is that not true?

Yet clearly the bits are being fetched from elsewhere. When I
print floatVarA as a float its value is correct and unchanging.
When I cast that same 32-bit variable to int the code is clearly
looking at something which is changing and which therefore
must be something other than the 32 floatVarA bits which are
demonstrably NOT changing.

Maybe that is the issue.  Maybe (int)floatVarA   IS   looking at
something outside of the scope of main() which might reasonably
be expected to change.  But if that is the case then the cast is going
to the wrong place.  The variable, however cast, should be fetched
from the same location in memory whatever confusion might then
result in the interpretation of the fetched bits.  Yes?



You also don't demonstrate that the calls to printf are modifying the caller's state.

(int)floatVarA = 0.000000 <<=== initial value 0?? floatVarA = 1234.000000 (int)floatVarA = 1234.000000 <<=== changed floatVarB = 5678.000000 (int)floatVarA = 5678.000000 <<=== changed again floatVarA = 1234.000000

My immediate interpretation of your result is that
the compiler is doing alias analysis - it knows what can and cannot be
legally done in conversions between unrelated types (int and float),

Again I am not concerned with the misinterpretation of the bits, just which location are those bits coming from.


and it uses this knowledge to generate code that is more optimal under
the assumption that the programmer is following the rules of C.  When
you break those rules, you break that assumption - lie to your
compiler and you will get bad code as a result.


Try compiling your code with -Wall, which will help point out your errors.
On 08/21/2012 10:20 AM, Ángel González wrote:

Compiling with -Wall it will complain about passing an int to a %f
parameter.
The program shown by Jeff is consistent with printf(..., float) moving
the value to a float register and printf("%f") printing the code from
that register.

I guess, in summary, my question is now, "Does re-casting a variable ever cause data (however misinterpreted) to be fetched from a different location?" I should think it would not.

Again, thank you for your replies.

Jeff Barry


PS: My eMail address, a.GNUbie@myLetters.US, is meant to imply that I am new to the specifics of GNU. I am hardly new to low level coding in case my eMail address implied that to you.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]