-4

I have this code in C-

#include <stdio.h>
void main(void)
{
    int a=90;
    float b=4;
    printf("%f",90%4);
}

It gives an output 0.0000,I am unable to understand why??? i know that 90%4 returns 2 and the format specifier specified is %f,which is for double,but what I expect is- That it will give an error,but it is showing 0.0000 as output. Can someone please explain why?

Frosted Cupcake
  • 1,909
  • 2
  • 20
  • 42
  • Why do you think it will throw an error? Also, always use `int main()` with `return 0;` – CinCout Sep 14 '15 at 13:25
  • because of type mismatch,format specifier is %f and value returned is int. – Frosted Cupcake Sep 14 '15 at 13:26
  • And if it will not show error,then why it is not displaying 2.0000 – Frosted Cupcake Sep 14 '15 at 13:27
  • 1
    [`void main()` is wrong](http://stackoverflow.com/q/204476/995714) – phuclv Sep 14 '15 at 14:08
  • 1
    What's the point of the useless `a` and `b` here? Do you mean `printf("%f", a % b);`? That won't even compile as `%` can only operate on integer types – phuclv Sep 14 '15 at 14:21
  • @LưuVĩnhPhúc By the very link you provided, void main (void) is not necessarily wrong, see [this answer](http://stackoverflow.com/a/31263079/584518). Making such comments about the form of main is not productive, especially when the comments are incorrect. – Lundin Sep 14 '15 at 14:40
  • @Lundin of course I know `void main()` is valid in a freestanding environment. But do you think the OP's running one of them? Most questions that use `void main()` are from Indians who still use Turbo C – phuclv Sep 14 '15 at 14:43
  • @LưuVĩnhPhúc It is not clear that void main() is forbidden even in hosted environments. The standard is not clear, it just says "or in some other implementation-defined manner" as was discussed in the linked answer, with references to the C rationale etc. The OP didn't specify any platform for his program, nor is the form of main relevant to the question. As for people who still use Borland Turbo, they won't listen to reason anyhow, so you might as well be talking to a wall. – Lundin Sep 14 '15 at 14:51

6 Answers6

6

The type of 90%4 will be int.

The behaviour on using %f as the format specifier for an int is undefined.

The output could be 2, it could be 0. The compiler could even eat your cat.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
5

This discrepancy comes about because the compiler and library do not communicate regarding types. What happens is that your C compiler observes that printf is a variadic function taking any number of arguments, so the extra arguments get passed per their individual types. If you're lucky, it also parses the format string and warns you that the type doesn't match:

$ gcc -Wformat -o fmterr fmterr.c
fmterr.c: In function ‘main’:
fmterr.c:6:2: warning: format ‘%f’ expects argument of type ‘double’, 
but argument 2 has type ‘int’ [-Wformat=]
  printf("%f",90%4);
  ^

But this is still just a warning; you might have replaced printf with a function with different behaviour, as far as the compiler is concerned. At run time, floating point and integer arguments may not even be placed in the same place, and certainly don't have the same format, so the particular result of 0.0 is not guaranteed. What really happens may be related to the platform ABI. You can get specified behaviour by changing the printf argument to something like (float)(90%4).

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
2

%f expects a double and you pass int(90%4=2) in printf. Thus ,leading to Undefined Behaiour and can give output anything .

You need to explicitly cast -

printf("%f",(double)(90%4));   

Don't try this as compiler will generate an error (as pointed by @chux Sir )-

printf("%f",90%(double)4);   
ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • The two versions aren't equivalent, as the first will perform the modulo calculation on two doubles, adding decimals if applicable, but also possibly adding floating point inaccuracy to the result. While the latter version will perform the calculation on integers. – Lundin Sep 14 '15 at 14:35
  • @Lundin `printf("%f",90%(double)4);` is not even legal C code. "invalid operands to binary % (have 'int' and 'double')" – chux - Reinstate Monica Sep 14 '15 at 14:46
  • @chux I didn't compiled that. But it turns out it will make unhappy .I will fix it – ameyCU Sep 14 '15 at 14:49
  • 1
    @chux Oh right, I had forgotten that in the specific case of the % operator the C standard enforces int. You'd have to use fmod() or some function like that. – Lundin Sep 14 '15 at 14:55
2

printf is a variadic function. Such functions are obscure, with no type safety worth mentioning. What such functions do is to implicitly promote small integer types to type int and float to double, but that is it. It is not able to do more subtle things like integer to float conversion.

So printf in itself can't tell what you passed on it, it relies on the programmer to specify the correct type. Integer literals such as 90 are of type int. With the %f specifier you told printf that you passed a double, but actually passed an int, so you invoke undefined behavior. Meaning that anything can happen: incorrect prints, correct prints, program crash etc.

An explicit cast (double)(90%4) will solve the problem.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

In short: there is no error checking for format specifiers. If your format is looking for a double, then whatever you pass as an argument (or even if you pass nothing) will be interpreted as a double.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
-1

By default, 90%4 gives an integer. If you print integer with %f specifier, it will print 0.

For example, printf("%f", 2); will print 0.

You typecast result with float, you will get 2.00000.

printf("%f",(float) (90%4)); will print 2.00000

Hope it clarifies.

Tlacenka
  • 520
  • 9
  • 15
Austin
  • 1,709
  • 20
  • 40
  • 3
    `printf("%f", 2);` will invoke undefined behavior, it may print anything. See all the other answers. – Lundin Sep 14 '15 at 13:38
  • it will print 0, I bet on it. – Austin Sep 14 '15 at 13:38
  • 2
    How undefined is undefined behavior, do you think? – Lundin Sep 14 '15 at 13:40
  • 4
    How much do you bet on the fully standards-compliant C compiler that I maintain printing 0? – Bathsheba Sep 14 '15 at 13:43
  • Please check this in any standard compiler. I just gave try here (ubuntu gcc, g++). It prints 0. – Austin Sep 14 '15 at 14:01
  • Sorry, I did not understand your comment. What result you got? Please let me know. – Austin Sep 14 '15 at 14:08
  • 3
    On *your* machine, with *your* compiler, it prints 0. Because the standard does not define what will happen with this type of argument mismatch, there's no guarantee that another compiler will generate the same result. It might, but you can't depend on that. – dbush Sep 14 '15 at 14:12
  • Try`printf("%e", some_int);` (e not f) to get some insight to the undefined behavior you are experiencing. – chux - Reinstate Monica Sep 14 '15 at 14:53