0

Here is the code i was trying.I could not comprehend the output i got.Why is output some garbage value here and not 10?

#include<stdio.h>
#include<string.h>
void f(int);
void (*foo)(float)=f;
int main()
{

  foo(10);
   return 0;

}

void f(int i)
{
   printf("%d\n",i);
}

Output is some garbage value.

3
  • 1
    Did you enable all warnings and then compile it? It tells you why. Commented Jun 25, 2012 at 12:15
  • It did give warning but it just said incompatible.thats all. Commented Jun 25, 2012 at 12:22
  • 1
    Read warnings! They are your friends. Commented Jun 25, 2012 at 13:20

5 Answers 5

4

This is undefined behaviour.

You're calling f, which is a function taking an int, as if it were a function taking a float. The actual behaviour will depend on how the calling conventions of your platform work - for example, if int and float parameters are passed in the same register or the same stack slot the result will be that of aliasing the floating-point bit pattern representing 10.0f as an int. If on the other hand int and float are passed differently the result will be whatever garbage was in the appropriate register or stack slot.

Also, because this is undefined behaviour the compiler is at liberty to do whatever it likes, and if the optimiser is enabled it may well do.

Sign up to request clarification or add additional context in comments.

2 Comments

What if stack is used for parameters?is stack not used for that purpose at all in any platforms?
Absolutely it is; see en.wikipedia.org/wiki/X86_calling_conventions for some of the possibilities.
4

Why is output some garbage

Because you lie to the compiler.

You tell it foo is a pointer to a function that accepts a float ... but then point it to a function that accepts an int.

Don't lie to the compiler

1 Comment

+1 Best advice. But perhaps one day mankind will triumph over the savage compiler!
4

Compiers usually emit warnings or errors in this case, e.g. GCC says:

program.c:4: warning: initialization from incompatible pointer type

Intel C Compiler is more verbose:

program.c(4): warning #144: a value of type "void (*)(int)" cannot be used to initialize an   entity of type "void (*)(float)"
  void (*foo)(float)=f;
                     ^

Besides possible conversion of argument value 10 to floating point, there is another option if you are running on a 64-bit machine - calling convention. Integer arguments are passed through the regular integer CPU registers (RDI, RSI, etc.) while floating-point arguments are passed in the SSE registers (XMM0, XMM1, etc.). Even if somehow the floating point value was compatible with the integer one, the called function will receive its argument in different register (XMM0) than the one it will consult for the value (RDI).

On a 32-bit machine both integer and floating point arguments are passed on the stack. What you end up with is 1092616192 which is just 10.0 in IEEE 754 single-precision floating point representation:

1092616192 = 0|10000010|01000000000000000000000
             | |        |
             | |        +---> significand = 1 + 2^(-2) = 1.25
             | |
             | +------------> exponent = 130 - 127 = +3
             |
             +--------------> sign = 0 (positive)

1.25 * 2^3 = 1.25 * 8 = 10.0

Comments

2

Because of undefined behavior.

The call through foo() converts the integer 10 to float, which is then interpreted as an int by f().

I'm pretty sure this isn't well-defined.

Comments

1

Because of the different prototypes. The compiler treats "10" as a float, and uses its floating-point representation to call f(), which in turn treats it as an ineteger, whose binary representation does not have the value "10".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.